Spring AOP中增强知识

Spring中增强:包含横切代码和方位信息  ,增强继承关系如下图:

   

Advice :其实就是一个增强的标志接口,没有实际的方法需要实现。

前置增强(BeforeAdvice):Spring中只支持方法级别的增强操作,所以MethodBeforeAdvice是目前可用的前置增强,而BeforeAdvice是为了后面扩展。

后置增强(AfterRetruningAdvice) :表示在目标方法执行后实施增强

环绕增强(MethodInterceptor):表示在目标方法执行前后实施增强

异常抛出增强(ThrowsAdvice) 表示在目标方法抛出异常后实施增强

引介增强(IntroductionInterceptor)表示在目标类中添加一些新的方法和属性

 

 

1.前置增强案例

       增强类代码如下:      

/前置增强
public class GreeetingBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(this.getClass().getName() + "." + method.getName());
        String name = (String) objects[0];
        System.out.println("How are you Mr " + name);
    }
}

 

通过硬编码的方式调用前置增强

public static void textFactoryBean() {
        //目标类对象
        Waiter waiter = new NaviWaiter();
//        前置增强
        GreeetingBeforeAdvice greeetingBeforeAdvice = new GreeetingBeforeAdvice();
//        后置增强
        GreetingAfterAdvice greetingAfterAdvice = new GreetingAfterAdvice();
//        代理工厂
        ProxyFactory factory = new ProxyFactory();
//        设置目标类
        factory.setTarget(waiter);
//        设置增强
        factory.addAdvice(greeetingBeforeAdvice);
//        设置后置增强
        factory.addAdvice(greetingAfterAdvice);
//        获取代理对象
        Waiter proxy = (Waiter) factory.getProxy();
        proxy.greetTo("zhang");
        proxy.serveTo("zhang");
    }

 

通过Spring配置文件来设置 增强数据

 <!--设置前置代理-->

代理对象 <bean id="target" class="com.example.AOP.BeforeAdvice.NaviWaiter"/>
  //增强Bean <bean id="beforehance" class="com.example.AOP.BeforeAdvice.GreeetingBeforeAdvice"/> <bean id="afterAdvice" class="com.example.AOP.BeforeAdvice.GreetingAfterAdvice"/> <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"//代理工厂Bean 是ProxyFactory的实现类 p:proxyInterfaces="com.example.AOP.BeforeAdvice.Waiter"//代理接口 p:interceptorNames="beforehance,afterAdvice"//织入的增强 p:target-ref="target"
//其中 target表示代理目标类 proxyInterfaces表示代理所要实现的接口,可以是多个接口, interceptorNames:表示需要织入目标对象的Bean列表,
optimize 当设置为True 强制使用CGLib动态代理, proxyTargetClass是否对类进行代理吗,设置为true表示使用CGLib代理
interceptorNames 接收的是Bean的名称而非Bean类 />


 

 NaviWaiter实现Waiter接口后,自己写就行了

 2.后置增强案例

   后置增强是在目标方法调用完后执行,代码如下:

     

//后置增强
public class GreetingAfterAdvice implements AfterReturningAdvice {
    /*
    其中 Object object 表示目标方法的返回值
          Method method 表示目标方法
          objects 表示方法参数
          Object o1表示目标类实例
     */
    @Override
    public void afterReturning(Object object, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("please enjoy youself");
    }
}

 

     添加后置增强配置文件如上:

3.环绕增强允许在方法前后加入横切逻辑代码。  Spring使用MethodInterceptor作为环绕增强的接口,

    

//环绕增强
public class GreetingInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
//        获取目标方法参数
        Object[] arguments = invocation.getArguments();
        String clientName = (String) arguments[0];
        System.out.println("How are you Mr " + clientName + " !");
        Object proceed = invocation.proceed();
        System.out.println("bye bye " + clientName + " !");
        return proceed;
    }
}

环绕增强配置

 <!--环绕增强配置-->
    <bean id="NaviWaiter" class="com.example.AOP.BeforeAdvice.NaviWaiter"/>
    <bean id="GreetAround" class="com.example.AOP.BeforeAdvice.GreetingInterceptor"/>
    <bean id="wwwwss" class="org.springframework.aop.framework.ProxyFactoryBean" p:proxyTargetClass="true"
          p:interceptorNames="GreetAround" p:target-ref="NaviWaiter"/>

 

4.异常抛出增强   通过实现ThrowsAdvice接口,并设置默认规定方法用于处理异常抛出后的问题。  此接口是一个标签接口,没有任何实际方法,但必须按如下格式处理异常抛出增强方法

   void  afterThrowing([Method method,Object[] object,Object target],Throwable)此方法的前面三个参数要么都不提供,要么都要提供,Throwable必须提供

  5.引介增强案例

     

//引介增强
public class ControllerPerformaceMonitor extends DelegatingIntroductionInterceptor implements Monitorable {

    private ThreadLocal<Boolean> local = new ThreadLocal<Boolean>();

    @Override
    public void setMonitorable(boolean active) {
        local.set(active);
    }
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        Object object = null;
        if (local.get() != null && local.get()) {
            PerFormanceMonitor.begin(mi.getClass().getName() + "." + mi.getMethod().getName());
            object = super.invoke(mi);
            PerFormanceMonitor.end();
        } else {
            object = super.invoke(mi);
        }
        return object;
    }

 

   配置文件

 <!--引介增强-->
    <bean id="Frumservice" class="com.example.AOP.ForumServiceImpl"/>
    <bean id="yicontro" class="com.example.AOP.introduceAdivice.ControllerPerformaceMonitor"/>
    <bean id="smtext" class="org.springframework.aop.framework.ProxyFactoryBean"
          <!--引介增强所要实现的接口-->
          p:interfaces="com.example.AOP.introduceAdivice.Monitorable"
          p:target-ref="Frumservice"
    <!--增强类-->
          p:interceptorNames="yicontro"
    <!--必须使用CGLib方式,因为引介增强需要创建子类-->
          p:proxyTargetClass="true"
    />

 

  

 

posted @ 2017-11-08 22:20  张秀杰  阅读(1016)  评论(0编辑  收藏  举报