AOP增强详解

增强是AOP的核心部分之一,它包含逻辑代码和方位,增强就是一重最简单的切面。
增强的类型:

  1. 前置增强
  2. 后置增强
  3. 环绕增强
  4. 异常抛出增强
  5. 引介增强
package com.smart.advice; 

public interface Waiter { //接口
   void greetTo(String name);
   void serveTo(String name);
}
package com.smart.advice;

public class NaiveWaiter implements Waiter {//接口实现类(目标类)

    public void greetTo(String name) {
        System.out.println("greet to "+name+"...");
    }

    public void serveTo(String name){
        System.out.println("serving "+name+"...");
    }
}
package com.smart.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice; //增强类

public class GreetingBeforeAdvice implements MethodBeforeAdvice {//定义的一个接口,before是唯一的方法,par1 目标类的方法,par2 目标类的入参,par3 目标类
    public void before(Method method, Object[] args, Object obj) throws Throwable {
        String clientName = (String)args[0];
        System.out.println("How are you!Mr."+clientName+".");
    }
}
package com.smart.advice;

import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import static org.testng.Assert.*;
import org.testng.annotations.*;

public class BeforeAdviceTest {

    @Test
    public void before() {
        Waiter target = new NaiveWaiter(); //目标类
        BeforeAdvice  advice = new GreetingBeforeAdvice();//增强类
        ProxyFactory pf = new ProxyFactory();  //代理
        pf.setInterfaces(target.getClass().getInterfaces());//指定代理的接口
        pf.setOptimize(true);//指定底层处理方式为CGlib
        pf.setTarget(target);//指定目标类
        pf.addAdvice(advice);//指定增强

        Waiter proxy = (Waiter)pf.getProxy(); //获得代理
        proxy.greetTo("John");
        proxy.serveTo("Tom");
    }
}

主要思想创建前置增强,使用代理。
ProxyFactory 是一个代理工厂,他的底层就是使用jdk动态代理或者CGlib动态代理,根据情况自动选择,也可以使用setOptimize(true)强制使用CGlib代理。
下面介绍一下spring中配置增强的方法:

    <bean id="greetingBefore" class="com.smart.advice.GreetingBeforeAdvice" />
    <bean id="greetingAfter" class="com.smart.advice.GreetingAfterAdvice" />
    <bean id="greetingAdvice" class="com.smart.advice.GreetingBeforeAdvice" />
    <bean id="greetingAround" class="com.smart.advice.GreetingInterceptor" />
    <bean id="target" class="com.smart.advice.NaiveWaiter" />
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:proxyInterfaces="com.smart.advice.Waiter"//指定接口
        p:target-ref="target"//指定目标类
        p:interceptorNames="greetingAround【,greetingAfter】" />//指定增强,可以指定多个增强,标准格式为:
    //  <property name = "interceptorNames">
    //      <list>
    //          <idref local = "greetingBefore"/>
    //          <idref local = "greetingAfter"/>
    //      </list>
    //  </property>
    //  p:optimize = true;//指定底层实现方式

通过spring配置的增强如何使用?见下面代码:

    @Test
    public void advice() {
        String configPath = "com/smart/advice/beans.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);//获取资源
        Waiter waiter = (Waiter)ctx.getBean("waiter");//获取bean,通过spring配置,该Bean以及被加强
        waiter.greetTo("John");
    }

对于后置增强:其他使用方法和前置增强一样。下面我们看看如何定义后置增强,

package com.smart.advice;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class GreetingAfterAdvice implements AfterReturningAdvice {//实现指定接口,和指定方法即可

    public void afterReturning(Object returnObj, Method method, Object[] args,
            Object obj) throws Throwable {
        System.out.println("Please enjoy yourself!");
    }
}

环绕增强的定义方法:

package com.smart.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class GreetingInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object[] args = invocation.getArguments();
        String clientName = (String)args[0];
        System.out.println("How are you!Mr."+clientName+".");

        Object obj = invocation.proceed();

        System.out.println("Please enjoy yourself!");

        return obj;
    }
}

异常增强的定义方法:

package com.smart.advice;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;

public class TransactionManager implements ThrowsAdvice {//同样实现指定类,和指定方法
    public void afterThrowing(Method method, Object[] args, Object target,
            Exception ex) throws Throwable {
        System.out.println("-----------");
        System.out.println("method:" + method.getName());
        System.out.println("抛出异常:" + ex.getMessage());
        System.out.println("成功回滚事务。");
    }
}

引介增强:它不是在目标方法周围织入增强,而是为目标类创建新的方法和属性,连接点就是类级别的。
自己不实现某一个接口,但是代理实现了。返回的是代理,具有某些特殊功能
它能干嘛呢?比如我们织入增强,需要手动控制增强的开启与关闭,这时就要使用引介增强了。

package com.smart.introduce;

import org.aopalliance.intercept.MethodInvocation;
//引介增强提供的实现类,所以这里不是实现,而是继承
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
public class ControllablePerformaceMonitor
        extends
            DelegatingIntroductionInterceptor implements Monitorable, Testable {
    //线程局部变量,支持范型
    private ThreadLocal<Boolean> MonitorStatusMap = new ThreadLocal<Boolean>();
    //属性注入
    public void setMonitorActive(boolean active) {
        MonitorStatusMap.set(active);
    }
    public Object invoke(MethodInvocation mi) throws Throwable {
        Object obj = null;
        //获取线程局部变量,通过这个变量控制是否进行增强
        if (MonitorStatusMap.get() != null && MonitorStatusMap.get()) {
            PerformanceMonitor.begin(mi.getClass().getName() + "."
                    + mi.getMethod().getName());
            obj = super.invoke(mi);
            PerformanceMonitor.end();
        } else {
            obj = super.invoke(mi);
        }
        return obj;
    }
    public void test() {
        // TODO Auto-generated method stub
        System.out.println("dd");
    }
}
    <bean id="pmonitor" class="com.smart.introduce.ControllablePerformaceMonitor" />
    <bean id="forumServiceTarget" class="com.smart.introduce.ForumService" />
    <bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
        //引介增强实现的接口
        p:interfaces="com.smart.introduce.Monitorable"
        //目标类
        p:target-ref="forumServiceTarget"
        //引介增强
        p:interceptorNames="pmonitor" 
        //引介增强必须使用CGlib动态代理,这里必须设置为true
        p:proxyTargetClass="true" />

    @Test
    public void introduce(){
        String configPath = "com/smart/introduce/beans.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
        ForumService forumService = (ForumService)ctx.getBean("forumService");
        forumService.removeForum(10);
        forumService.removeTopic(1022);
        Monitorable moniterable = (Monitorable)forumService;
        moniterable.setMonitorActive(true);
        forumService.removeForum(10);
        forumService.removeTopic(1022); 
    }

增强都是需要实现特定的接口,和方法、
然后通过代理,设置代理的接口,目标类,增强,底层代理方式。从而实现增强的织入,可是这种织入,是对目标类的所有方法而言的。如果我们只想对目标类的某一方法进行处理,我们该如何处理呢?这时候就要使用切面了。
增强+切点=切面。增强就是最简单的一种切面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值