Spring AOP 定义切入点

来源:互联网 发布:南京软件测试工资待遇 编辑:程序博客网 时间:2024/04/29 07:20

首先我们编写了通知advice,但是我们还不能表达在应用系统的什么地方应用这些通知,切入点决定了一个特定类的特定方法是否满足特定规则,如果满足则通知就应用到该方法上,Spring的切入点可以让我们灵活的定义在什么地方应用通知。 

Spring的切入点框架的核心接口PointCut 

Java代码 复制代码 收藏代码
  1. public interface PointCut {   
  2.   ClassFilter getClassFilter();   
  3.   MethodMatcher getMethodMatcher();   
  4. }  
[java] view plaincopy
  1. public interface PointCut {  
  2.   ClassFilter getClassFilter();  
  3.   MethodMatcher getMethodMatcher();  
  4. }  


PointCut 是根据方法和类决定在什么地方织入通知的。 

ClassFilter决定了一个类是否符合通知的要求 
Java代码 复制代码 收藏代码
  1. public interface ClassFilter{   
  2.    boolean matches(Class clazz);//根据类名判断   
  3. }  
[java] view plaincopy
  1. public interface ClassFilter{  
  2.    boolean matches(Class clazz);//根据类名判断  
  3. }  

实现了这个接口的类决定了以参数传进来的类是否应该被通知,它相当于一个类的过滤器,一般根据类名过滤,另外这个接口总是包含一个简单的ClassFilter的实现ClassFilter.TRUE,它是规范任何类的ClasFilter实例,它适用于只创建只根据方法来决定是否是应用通知的切入点。 

MethodMether决定了一个类的一个方法是否符合通知的要求 
Java代码 复制代码 收藏代码
  1. public interface MethodMether{   
  2.    //决定一个类的一个方法是否被通知,AOP代理被创建的时候,调用一次这个方法,这个方法的结果决定了是否应用通知   
  3.    boolean mathces(Method m,Class target);   
  4.   //决定MethodMether是静态还是动态,静态:false,通知总是被执行,动态true:根据运行时方法的参数值决定通知是否被执行。   
  5.    public boolean isRuntime();   
  6.    //如果是静态切入点,此方法不会被调用   
  7.    //如果是动态切入点,目标对象方法每次被调用的时候,此方法被调用。   
  8.    public boolean matches(Method m,Class target,Object arg[]);   
  9. }  
[java] view plaincopy
  1. public interface MethodMether{  
  2.    //决定一个类的一个方法是否被通知,AOP代理被创建的时候,调用一次这个方法,这个方法的结果决定了是否应用通知  
  3.    boolean mathces(Method m,Class target);  
  4.   //决定MethodMether是静态还是动态,静态:false,通知总是被执行,动态true:根据运行时方法的参数值决定通知是否被执行。  
  5.    public boolean isRuntime();  
  6.    //如果是静态切入点,此方法不会被调用  
  7.    //如果是动态切入点,目标对象方法每次被调用的时候,此方法被调用。  
  8.    public boolean matches(Method m,Class target,Object arg[]);  
  9. }  


Advisor 

   大多数的切面由通知和切入点组成,因此Spring把advice和pointcut组合为一个对象,PointcutAdvisor 
Java代码 复制代码 收藏代码
  1. public interface PointcutAdvisor{   
  2.    PointCut getPointCut();   
  3.    Advice getAdvice();   
  4. }   
  5. //大多数的Spring自带的切入点都有一个对应的PointcutAdvisor.  
[java] view plaincopy
  1. public interface PointcutAdvisor{  
  2.    PointCut getPointCut();  
  3.    Advice getAdvice();  
  4. }  
  5. //大多数的Spring自带的切入点都有一个对应的PointcutAdvisor.  


静态/动态切入点比较 

静态切入点只在代理被创建的时候执行一次,而不是在运行期间每次方法调用都执行,因此性能比动态切入点好,因此静态切入点是我们的首选,Spring为创建静态切入点提供了父类StaticMethodMatcherPointcut,继承它并实现isMatch方法就可以了 

Spring提供的静态切入点 

(1)NameMatchMethodPointcut 
这个类有2个主要方法: 
Java代码 复制代码 收藏代码
  1. public void setMappedName(String name)   
  2. public void setMappedNames(String[] names)  
[java] view plaincopy
  1. public void setMappedName(String name)  
  2. public void setMappedNames(String[] names)  

事例: 
有一个接口类 MyInterfaceA ,包含3个方法,set1,set2,get3 ,有一个实现类MyClassAImpl;我们想配置set方法的切入点,如下实现: 
Java代码 复制代码 收藏代码
  1.  <beans>   
  2.     //目标对象   
  3.     <bean id="MyClassATarget" class="MyClassAImpl"></bean>   
  4.     //通知   
  5.     <bean id="myAdvice" class="..."></bean>   
  6.     //定义切面   
  7.     <bean id="myAdvisor" class="....NameMatchMethodPointcut">   
  8.           //方法过滤,注入切入点   
  9.           <property name="mappedName">   
  10.                <value>set*</value>   
  11.           </property>   
  12.           //注入通知   
  13.           <property name="advice">   
  14.                <ref bean="myAdvice"/>   
  15.           <property>   
  16.     </bean>   
  17.    //配置代理   
  18.     <bean id="MyClassAProxy" class=".....ProxyFactoryBean">   
  19.        //代理的接口   
  20.        <property name="proxyInterfaces">   
  21.            <value>MyInterfaceA</value>   
  22.        <property>   
  23.        //配置切面   
  24.        <property name="interceptorNames">   
  25.            <list>   
  26.                <value>myAdvisor</value>   
  27.            </list>   
  28.        <property>   
  29.        //配置目标对象   
  30.        <property name="target">   
  31.            <ref bean="MyClassATarget"/>   
  32.        <property>   
  33.     </bean>   
  34.  </beans>   
  35.   
  36. //整个过程可以如下几步:   
  37. 1  编写接口:myinterface   
  38. 2  编写接口的实现myImpl并配置为bean:myImplTarget      
  39. 3  编写通知myAdvice并配置为bean:myAdvice   
  40. 4  配置切面myAdvisor,切面中注入切入点(set*)和通知myAdvice   
  41. 5  配置代理myImplProxy,注入接口类myinterface,注入切面myAdvisor,注入目标对 象myImplTarget  
[java] view plaincopy
  1.  <beans>  
  2.     //目标对象  
  3.     <bean id="MyClassATarget" class="MyClassAImpl"></bean>  
  4.     //通知  
  5.     <bean id="myAdvice" class="..."></bean>  
  6.     //定义切面  
  7.     <bean id="myAdvisor" class="....NameMatchMethodPointcut">  
  8.           //方法过滤,注入切入点  
  9.           <property name="mappedName">  
  10.                <value>set*</value>  
  11.           </property>  
  12.           //注入通知  
  13.           <property name="advice">  
  14.                <ref bean="myAdvice"/>  
  15.           <property>  
  16.     </bean>  
  17.    //配置代理  
  18.     <bean id="MyClassAProxy" class=".....ProxyFactoryBean">  
  19.        //代理的接口  
  20.        <property name="proxyInterfaces">  
  21.            <value>MyInterfaceA</value>  
  22.        <property>  
  23.        //配置切面  
  24.        <property name="interceptorNames">  
  25.            <list>  
  26.                <value>myAdvisor</value>  
  27.            </list>  
  28.        <property>  
  29.        //配置目标对象  
  30.        <property name="target">  
  31.            <ref bean="MyClassATarget"/>  
  32.        <property>  
  33.     </bean>  
  34.  </beans>  
  35.   
  36. //整个过程可以如下几步:  
  37. 1  编写接口:myinterface  
  38. 2  编写接口的实现myImpl并配置为bean:myImplTarget     
  39. 3  编写通知myAdvice并配置为bean:myAdvice  
  40. 4  配置切面myAdvisor,切面中注入切入点(set*)和通知myAdvice  
  41. 5  配置代理myImplProxy,注入接口类myinterface,注入切面myAdvisor,注入目标对 象myImplTarget  


    
(2)RegexpMethodPointcut正则表达式切入点 
整个过程同上,但在配置切面时有所不同,见蓝色部分代码 
Java代码 复制代码 收藏代码
  1. //定义切面   
  2.  <bean id="myAdvisor" class="....RegexpMethodPointcut">   
  3.        //方法过滤,注入切入点   
  4.        [color=blue]<property name="pattern">   
  5.             <value>.*get.+By.+</value>   
  6.        </property>[/color]          //注入通知   
  7.        <property name="advice">   
  8.             <ref bean="myAdvice"/>   
  9.        <property>   
  10.  </bean>  
[java] view plaincopy
  1. //定义切面  
  2.  <bean id="myAdvisor" class="....RegexpMethodPointcut">  
  3.        //方法过滤,注入切入点  
  4.        [color=blue]<property name="pattern">  
  5.             <value>.*get.+By.+</value>  
  6.        </property>[/color]          //注入通知  
  7.        <property name="advice">  
  8.             <ref bean="myAdvice"/>  
  9.        <property>  
  10.  </bean>  

正则表达式: 
.:匹配任何单个字符 例如:setF. 匹配setFi,但不匹配setF 和 setFii 
+:匹配前一个字符一次或者多次,例如setF.+ 匹配setFBar和setFB,不匹配setF 
*:匹配前一个字符0次或者多次,例如setF.* ,同上并匹配setF 
\:匹配任何正则表达式符号,例如\.setF ,匹配bar.setF ,不匹配setF
0 0
原创粉丝点击