spring aop支持

来源:百度文库 编辑:神马文学网 时间:2024/04/28 14:34:12
   

Spring只支持方法的JoinPoints,也就是Adivices将在方法执行的前后被引用,Spring不支持Field成员的Joinpoints,这是因为Spring的设计哲学中认为,支持Field成员的Joinpoints会破坏对象的封装性。

Advices

Advices实现了Aspectj的真正逻辑,根据蒋这些通知织入Targets的时机不同Spring提供了几种不同的通知,比如,BeforeAfterAroundThrow

1.Before

/**

 * 前置通知,在目标方法调用之前执行

 * @author Administrator

 *

 */

public class BeforeAdvicesTest implements MethodBeforeAdvice{

    public void before(Method method, Object[] args, Object target)

    throws Throwable {

        System.out.println("before execute");

     }

}

class="com.bhsc.AOP.target.TargetImple">

class="org.springframework.aop.framework.ProxyFactoryBean">

       

value="com.bhsc.AOP.target.TargetInterface"/>

       

       

          

             before

          

       

通知实现了MethodBeforeAdvice,在配置中建立了AdviceTarget,还使用了ProxyFactoryBean,这个类会被BeanFactoryApplicationContext,用来建立代理对象,并配置了实现的接口,在不指定目标方法时,Before Advice会被织入到接口上的所有方法。

AdviceTarget并不是动态代理中的代理对象,而是真实的对象,也就是动态代理中传入的真正的类。

拿动态代理来对比下:

Object  proxy  =  Proxy.newProxyInstance(Monkey.class.getClassLoader(), 

Monkey.class.getInterfaces(), 

new MyInvocationHandler( new Monkey())); 

 可以看到动态代理中,真正的类是new时候传入的,而Spring则配置在文件中注入了。

2.After Before类似

3.Around

如果要在方法执行的前后,加入Advices的逻辑,可以直接通过实现org.aopalliance.intercept.MethodInterceptor接口,与Before和After不同的是,在MethodInterceptor的invoke方法中,我们可以自行决定是否使用它的proceed()方法来执行目标对象的方法,proceed会回传方法执行后的Object结果,所以在invoke结束之前,有机会修改对象,或是回传一个完全不相干的对象。 

/**

 * Around通知,在真正执行某个方法前,会先插入Interceptor,如果有多个,则会一个个执行,然后执行method的方法,将执行流程转给下一个Interceptor,最后一层层返回堆栈,最后离开堆栈返回应用程序本身的流程。

 * @author Administrator

 *

 */

public class MethodInterceptorTest implements MethodInterceptor{

  public Object invoke(MethodInvocation methodInvocation) throws Throwable {

     System.out.println("execute method:"+methodInvocation.getMethod());

     Object result=null;

     result=methodInvocation.proceed();

     return result;

  }

}

class="com.bhsc.AOP.MethodInterceptorTest">

class="org.springframework.aop.framework.ProxyFactoryBean">

    

value="com.bhsc.AOP.target.TargetInterface"/>

    

    

        

           around

       

    

 

1.Throw 如果抛出的异常类型和发生的类型相同,那么就会执行通知方法。

前面的Advice,一定程度上也包括切入点,也就是一个类的所有方法,不过这些都是粗粒度的,事实上,我们可以定义更细粒度的,定义需要的方法,那就是PointCut


PointCutAdvisor

PointCut定义了Joinpoint的集合,表示Advice应用的时机(方法)。Spring中,用PointcutAdvisor表示PointCutAdvisor的结合,就是aspectPointcutAdvisorAdvisor的子接口:

public interface Advisor {


      Advice getAdvice();

   /**

    * @return whether this advice is associated with a particular target instance

    */

   boolean isPerInstance();

public interface PointcutAdvisor extends Advisor {

   /**

    * Get the Pointcut that drives this advisor.

    */

   Pointcut getPointcut();

}

分别有NameMatchMethodPointcutAdvisor、RegexpMethodPointcutAdvisor、ControlFlowPointcut


   1.NameMatchMethodPointcutAdvisor ,最基本的PointcutAdvisor,可以使用表达式指定Advice应用目标上的方法名称。

support.NameMatchMethodPointcutAdvisor">

       

       

 

 class="org.springframework.aop.framework.ProxyFactoryBean">

      

value="com.bhsc.AOP.target.TargetInterface"/>

      

      

         

            helloAdvisor

         

      

 

target中加入nihao方法:

public void nihao(String name){

System.out.println("你好 :"+name);

}

TargetInterface ti=(TargetInterface)ctx.getBean("helloProxy");

ti=(TargetInterface)ctx.getBean("helloAdvisorProxy");

ti.hello("lisi");

ti.nihao("lisi");


结果:

before execute

hello :lisi

你好 :lisi


   2.RegexpMethodPointcutAdvisor,使用正则来编写pointcut表达式。 

3.ControlFlowPointcut

用来判断某个方法中,是否要求目标对象执行某个方法,在执行时期动态决定是否介入Advice来提供服务,所以这是动态的PointCut功能

public class Some implements ApplicationContextAware{

      private TargetInterface target;

      
         public void setApplicationContext(ApplicationContext 

      applicationContext)throws BeansException {

         target=(TargetInterface)applicationContext.getBean("");

      }

      public void helloEverybody(){

         target.hello("wangwu");

         target.nihao("qw");

      }

      public void hello(){

         System.out.println("hello!");

      }

}  Some some=(Some)ctx.getBean("some");

boolean flag=true;

if(flag){

   some.helloEverybody();

}else{

   some.hello();

}


PointCutSpring中的PointCut是实现PointCut接口来实现的: 

public interface Pointcut {

   ClassFilter getClassFilter();

   MethodMatcher getMethodMatcher();

   Pointcut TRUE = TruePointcut.INSTANCE;

}

TruePointcutPointCut的简单实现,传回的ClassFilterClassFilter.TRUE,传回的MethodMatcherMethodMatcher.TRUE;


      ClassFilter决定一个类是否要应用Advicematches决定传入的类是否符合PointCur的定义。
   public interface ClassFilter {

   boolean matches(Class clazz);

   ClassFilter TRUE = TrueClassFilter.INSTANCE;

}

MethodMatcher决定某个方法是否要应用Advice


   public interface MethodMatcher {

   boolean matches(Method method, Class targetClass);

   boolean isRuntime();

   boolean matches(Method method, Class targetClass, Object[] args);

   MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;

如果是静态的PointCut,比如前面的NameMatchMethodPointcutAdvisor 

RegexpMethodPointcutAdvisor,则执行第一个方法,isRuntime返回FALSE,否则执行第二个方法,isRuntime返回true

如果有多个PointCut,还可以对它进行交集、并集的操作,通过ComposablePointcut类,可以操作它的intersectionunion方法。 

Introduction

是一种特殊的Advice,从行为上来看,它不像前面的BeforeAfter等,在方法前后介入服务,而是直接介入整个对象的行为,就好像凭空多了一些可操作的行为,为对象动态加入(Mixin)原先所没有的职责。

 

   class="onlyfun.caterpillar.OtherIntroduction" /> 


   

"org.springframework.aop.support.DefaultIntroductionAdvisor">

    

     
   

class="org.springframework.aop.framework.ProxyFactoryBean">

   

   value="onlyfun.caterpillar.ISome" /> 

     

    

      

         introductionAdvisor 

     

     

 

ApplicationContext ctx = new 

ClassPathXmlApplicationContext("Aop.xml");

ISome some=(ISome)ctx.getBean("proxyFactoryBean");

some.doSome();

//看起来像是增加了职责

((IOther)some).doOther();结果:

原来对象的职责。。。

增加的职责... 

Autoproxing

自动代理可以不用为每一个目标对象手动代理对象,使用自动代理,可以通过Bean名称或是Pointcut对比,自动为符合对比条件的目标对象建立代理对象。

1.BeanNameAutoProxyCreator

看一下前面的配置:

class="com.bhsc.AOP.target.TargetImple">

class="org.springframework.aop.framework.ProxyFactoryBean">

   

value="com.bhsc.AOP.target.TargetInterface"/>

   

   

      

         before

      

   

不仅要定于Advicetarget,还要定义一个代理对象,配置接口,target等,如果应用比较大,那么一个个配置是很麻烦的,PointcutAdvisor的定义只是对切入点更准确的定义,并不能解决配置繁琐的问题(NameMatchMethodPointcutAdvisor),不过Spring提供了自动代理,可以更加简单的配置。

比如,我们为Bean取好名称,xxxService,这样,就可以使用BeanNameAutoProxyCreator配置:

   class="org.springframework.

aop.framework.autoproxy.BeanNameAutoProxyCreator">

     

  

      

         *Service 

     

  

ISome someService=(ISome)ctx.getBean("someService");

someService.doSome();

((IOther)someService).doOther();

以后只要新增 

2.DefaultAdvisorAutoProxyCreator:自动搜寻