实现简单的AOP前置后置增强

Posted zumengjie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现简单的AOP前置后置增强相关的知识,希望对你有一定的参考价值。

AOP操作是我们日常开发经常使用到的操作,例如都会用到的spring事务管理.今天我们通过一个demo实现对一个类的某一个方法进行前置和后置的增强.

//被增强类
public class PetStoreService 
    //被增强方法
    public void placeOrder()
        System.out.println("place order");
        
//增强类
public class TransactionManager 

    //前置方法
    public void start() 
        System.out.println("start");
    

    //后置方法
    public void end() 
        System.out.println("end");
    

我们要做的就是在PetStoreService 中的placeOrder()执行前和执行后分别执行TransactionManager 中的start()和end()方法.下面我们将抽象出一个通知接口

 

//通知
public interface Advice 
    //执行增强方法
    public void invoke(InterceptorChain chain);

 

两个实现类,分别来执行start()和end()方法

//前置增强
public class BeforeAdvice implements Advice 
    //增强方法所属实例对象
    private Object object;
    //增强方法
    private Method method;
    //增强方法的参数
    private Object[] arguments;

    public BeforeAdvice(Object object, Method method, Object[] arguments) 
        this.object = object;
        this.method = method;
        this.arguments = arguments;
    

    //织入方法
    public void invoke(InterceptorChain chain) 
        try 
            //执行增强方法
            method.invoke(object, arguments);
            //返回
            chain.proceed();
         catch (Exception e) 
            System.out.println("执行after方法失败!!!!");
        
    
//后置增强
public class AfterAdvice implements Advice 
    //增强方法所属实例对象
    private Object object;
    //增强方法
    private Method method;
    //增强方法的参数
    private Object[] arguments;

    public AfterAdvice(Object object, Method method, Object[] arguments) 
        this.object = object;
        this.method = method;
        this.arguments = arguments;
    

    //织入方法
    public void invoke(InterceptorChain chain) 
        try 
            //返回
            chain.proceed();
            //执行增强方法
            method.invoke(object, arguments);
         catch (Exception e) 
            System.out.println("执行after方法失败!!!!");
        
    

两个方法中的构造子相同,都是给出通知类所需要的参数,而invoke()则是使用反射执行增强方法.

需要注意的是invoke()方法的参数,是一个拦截器链,两个方法都在执行自身Method方法前或者后执行了拦截器链中的方法.

下面是拦截器链

public class InterceptorChain 

    //拦截器链
    private List<Advice> adviceList;

    //需要增强的对象
    private Object object;

    //需要增强的方法
    private Method method;

    //当前需要执行方法的参数
    private Object[] arguments;

    //当前要执行的拦截器指针
    private int pointer = -1;

    //构造子
    InterceptorChain(Object obj, Method method, Object[] arguments) 
        this.object = obj;
        this.method = method;
        this.arguments = arguments;
        this.adviceList = new ArrayList<Advice>();
    

    //执行拦截器链
    public void proceed() 
        //如果当前指针指向拦截器末尾则执行自身得方法
        if (this.pointer == adviceList.size() - 1) 
            invoke();
            return;
        

        //指针+1
        pointer++;

        //获取需要执行的拦截器
        Advice advice = this.adviceList.get(pointer);

        //执行了拦截器
        advice.invoke(this);
    

    //执行原方法
    public void invoke() 
        try 
            method.invoke(object, arguments);
         catch (Exception e) 
            System.out.println("执行原有方法失败!!!");
        
    

    //增加拦截器

    public void addAdvice(Advice advice) 
        this.adviceList.add(advice);
    

这是一个核心类,其中的关键在于,客户端将把增强类添加到拦截器链中,在拦截器链中有一个指针pointer用来指向即将执行的增强方法.

下面是客户端调用

public class Main 
    public static void main(String[] args) throws Exception 
//需要增强的对象 PetStoreService petStoreService = new PetStoreService(); //增强 TransactionManager transactionManager = new TransactionManager(); //创建拦截器 InterceptorChain interceptorChain = new InterceptorChain(petStoreService, PetStoreService.class.getMethod("placeOrder"), new Object[0]); //增加拦截器链 interceptorChain.addAdvice(new BeforeAdvice(transactionManager, TransactionManager.class.getMethod("start"), new Object[0])); //增加拦截器链 interceptorChain.addAdvice(new AfterAdvice(transactionManager, TransactionManager.class.getMethod("end"), new Object[0])); //执行拦截器方法 interceptorChain.proceed();

我们分别创建需要增强的对象,还有增强对象.并把增强对象中的增强方法添加到拦截器链中.最终我们实现了,按照顺序执行完了拦截器链中的方法.感兴趣的同学可以debug试试看.

两个advice中调用拦截器的proceed()方法顺序,不一样的话,会有不同的结果哦.

 

以上是关于实现简单的AOP前置后置增强的主要内容,如果未能解决你的问题,请参考以下文章

AOP术语

创建增强类

Spring初学之annotation实现AOP前置通知和后置通知

Spring中的AOP和属性注入

Spring初学之annotation实现AOP前置通知后置通知返回通知异常通知。

Spring初学之xml实现AOP前置通知后置通知返回通知异常通知等