spring8——AOP之Bean的自動代理生成器

  對於上篇博客http://www.cnblogs.com/cdf-opensource-007/p/6464237.html結尾處提到的兩個問題,可使用spring提供的自動代理生成器解決。自動代理生成器可讓咱們把切面織入目標對象方法時不用再使用ProxyFactoryBean這個類來生成代理對象了,同時能夠把切面織入多個代理代理對象,而且在獲取代理對象時使用的是目標對象的id來獲取,這符合正常的使用習慣。html

  spring提供了兩個自動代理生成器,一個是DefaultAdvisorAutoProxyCreator,這一款代理生成器比較暴力,會把容器內全部的切面向全部的目標對象織入,並且切面只能是顧問的形式。另外一款自動代理生成器是BeanNameAutoProxyCreator,這一款代碼生成器就比較友好了,可讓咱們有選擇性的對目標對象和切面進行織入的操做,並且切面能夠是顧問或者通知的形式。程序員

下面咱們仍是以實驗的形式說明問題。分別提供兩個接口,和兩個實現類,用於目標對象的建立,在上篇博客實驗的基礎上咱們增長一個比較器的接口和實現類。spring

計算器接口:spring-mvc

public interface ICalculatorService {
    
    int add(int a,int b);
    
    int division(int a ,int b); 

}

比較器接口:mvc

public interface IComparatorService {
    
    void comparator(int a,int b);
}

計算器實現類:app

public class CalculatorServiceImpl implements ICalculatorService {

    @Override
    public int add(int a, int b) {
        return a+b;
    }

    @Override
    public int division(int a, int b) {
        return a/b;
    }

}

比較器實現類:ide

public class ComparatorServiceImpl implements IComparatorService {

    @Override
    public void comparator(int a, int b) {
        
        if(a > b){
            System.out.println(a+"比"+b+"大");
        }else if(a < b){
            System.out.println(a+"比"+b+"小");
        }else{
            System.out.println(a+"等於"+b);
        }

    }

}

依舊提供三個切面的實現類,分別是前置通知,環繞通知和後置通知。測試

public class TestMethodBeforeAdive implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("執行前置通知--->"+"正在執行的方法名爲"+method.getName());
    }

}

 

public class TestMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        
        System.out.println("執行環繞通知--->"+"正在執行的方法名爲"+invocation.getMethod().getName());
        
        Object[] arguments = invocation.getArguments();
        int a = (int)arguments[0];
        int b = (int)arguments[1];
        if(b == 0){
            System.err.println("除數不能爲0");
            return -1;
        }
        if(a == 0){
            return 0;
        }
        
        
        return invocation.proceed();
    }

}

 

public class TesAfterRunningAdive implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        
        System.out.println("執行後置通知--->"+"正在執行的方法名爲"+method.getName());
    }

}

配置文件:spa

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
                    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        
    <!-- 目標對象 -->            
    <bean id="comparatorServiceTarget" class="com.opensource.service.impl.ComparatorServiceImpl"/>
    <bean id="calculatorServiceTarget" class="com.opensource.service.impl.CalculatorServiceImpl"/>
    <!-- 通知 -->
    <bean id="methodBeforeAdive" class="com.opensource.service.impl.TestMethodBeforeAdive"/>
    <bean id="afterRunningAdive" class="com.opensource.service.impl.TesAfterRunningAdive"/>
    <bean id="methodInterceptor" class="com.opensource.service.impl.TestMethodInterceptor"/>
    <!-- 顧問 -->
    <bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <property name="advice" ref="methodInterceptor"/>
        <property name="mappedNames" value="division"/>
    </bean>
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                <value>calculatorServiceTarget</value>
                <value>comparatorServiceTarget</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>methodBeforeAdive</value>
                <value>afterRunningAdive</value>
                <value>advisor</value>
            </list>
        </property>
    </bean>
    
    
    
    
</beans>

測試類:代理

public class MyTest {
    public static void main(String[] args) {
        
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-bean.xml");
        ICalculatorService bean = (ICalculatorService)ac.getBean("calculatorServiceTarget");
        IComparatorService bean1 = (IComparatorService)ac.getBean("comparatorServiceTarget");
        int division = bean.division(10, 0);
        System.out.println("兩數相除商爲:"+division);
        System.err.println("---------------------------------------------------------");
        int add = bean.add(0, 2);
        System.out.println("兩數想加和爲:"+add);
        System.err.println("---------------------------------------------------------");
        bean1.comparator(0, 1);
        
        
        
    }


}

實驗結果:

這裏提一句:對於BeanNameAutoProxyCreatorbeanNamesinterceptorNames這兩個屬性能夠採用模糊匹配的方式,例如如下這種形式:

 

<property name="beanNames" value="*Target"/>

 

還有對顧問包裝通知時,一個顧問只能包裝一個通知,這也體現了顧問對於通知的精細化管理。

 

  最後說一點,咱們做爲程序員,研究問題仍是要仔細深刻一點的。當你對原理了解的有夠透徹,開發起來也就駕輕就熟了,不少開發中的問題和疑惑也就迎刃而解了,並且在面對其餘問題的時候也可作到舉一反三。固然在開發中沒有太多的時間讓你去研究原理,開發中要以實現功能爲前提,可等項目上線的後,你有大把的時間或者空餘的時間,你大可去刨根問底,深刻的去研究一項技術,爲以爲這對一名程序員的成長是很重要的事情。

相關文章
相關標籤/搜索