zoukankan      html  css  js  c++  java
  • 实现简单的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()方法顺序,不一样的话,会有不同的结果哦.

  • 相关阅读:
    winform制作自定义控件(入门)
    VB2012读取xml
    VB生成xml
    通宵疯狂积累VB.NET基础知识
    【转】vs2010下创建webservice
    React Native 快速入门之认识Props和State
    mac下 mysql / nginx 问题总汇
    Oracle例外定义
    mac os x 把reids nignx mongodb做成随机启动吧
    Oracle 记录
  • 原文地址:https://www.cnblogs.com/zumengjie/p/11335455.html
Copyright © 2011-2022 走看看