• spring AOP详解二


    AOP实例(通过Proxy代理模式)

         Spring AOP使用纯java实现,不需要专门的编译过程和类装载器,它在运行期间通过代理方式向目标类织入增强代码,它更侧重于提供一种和Spring IoC容器整合的AOP实现,在Spring中,我们可以无缝的将AOP,IoC,AspectJ整合在一起。

         Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理;

         JDK1.3以后,java提供了动态代理技术,允许开发者在运行期间动态的创建接口的代理实例,JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler,其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。

         下面我们来看一个JDK动态代理的例子:

         1.业务接口UserService.java

    package spring.aop.demo1;
    
    public interface UserService {
        void removeUser(int userId);
    }

         2.横切逻辑代理监视代码PerformanceMonitor.java

    复制代码
    package spring.aop.demo1;
    
    public class MethodPerformance {
    
        private long begin;
    
        private long end;
    
        private String serviceMethod;
    
        public MethodPerformance(String serviceMethod) {
            this.serviceMethod = serviceMethod;
            this.begin = System.currentTimeMillis();
        }
    
        public void printPerformance() {
            this.end = System.currentTimeMillis();
            long elapse = end - begin;
    
            System.out.println(serviceMethod + "花费" + elapse + "毫秒");
        }
    
    }
    复制代码
    复制代码
    package spring.aop.demo1;
    
    public class PerformanceMonitor {
    
        // 通过一个ThreadLocal保存调用线程相关的性能监视信息
        private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
    
        // 启动对一目标方法的性能监视
        public static void begin(String method) {
            System.out.println("begin monitor...");
            MethodPerformance mp = new MethodPerformance(method);
            performanceRecord.set(mp);
        }
    
        public static void end() {
            System.out.println("end monitor...");
            MethodPerformance mp = performanceRecord.get();
            mp.printPerformance();
        }
    
    }
    复制代码

        3.横切逻辑代理代码PerformanceHandler.java

    复制代码
    package spring.aop.demo1;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class PerformanceHandler implements InvocationHandler {
    
        private Object target;
    
        public PerformanceHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object arg0, Method arg1, Object[] arg2)
                throws Throwable {
            PerformanceMonitor.begin(target.getClass().getName() + "."
                    + arg1.getName());
            Object obj = arg1.invoke(target, arg2);// 通过反射机制调用目标对象的方法
            PerformanceMonitor.end();
            return obj;
        }
    
    }
    复制代码

          首先,我们实现InvocationHandler接口,该接口定义了一个invoke方法,proxy最是最终生成的一个代理实例,一般不会用到,参数arg1是被代理目标实例的某个具体的方法,通过它可以发起目标实例方法的反射调用;参数arg2是通过被代理实例某一个方法的入参,在方法反射调用时候使用,通过代理将横切逻辑代码和业务类的代码编织到了一起。

          我们在构造函数里通过target传入希望被代理的目标对象,将目标实例产地个method.inoke(),调用目标实例的方法。

         4.通过Proxy结合PerformanceHandler创建UserService接口的代理实例:

    复制代码
    package spring.aop.demo1;
    
    import java.lang.reflect.Proxy;
    
    public class UserServiceImpl implements UserService {
    
        @Override
        public void removeUser(int userId) {
            System.out.println("模拟删除用户:" + userId);
            try {
                Thread.currentThread().sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            UserService userService = new UserServiceImpl();
            // 将目标业务类和横切代码编织到一起
            PerformanceHandler handler = new PerformanceHandler(userService);
    
            // 根据编织了目标业务类逻辑和性能监视横切逻辑的InvocationHandler实例创建代理实例
            UserService proxy = (UserService) Proxy.newProxyInstance(userService
                    .getClass().getClassLoader(), userService.getClass()
                    .getInterfaces(), handler);
            
            proxy.removeUser(3);
    
        }
    }
    复制代码

    输出:

    begin monitor...
    模拟删除用户:3
    end monitor...
    spring.aop.demo1.UserServiceImpl.removeUser花费203毫秒

         说明:上面的代码完成业务类代码和横切代码的编制工作,并生成了代理实例,newProxyInstance方法的第一个参数为类加载器,第二个参数为目标类所实现的一组接口,第三个参数是整合了业务逻辑和横切逻辑的编织器对象。使用JDK代理模式有一个限制,即它只能为接口创建代理实例,这一点我们可以从Proxy.newProxyInstance的方法签名中就可以看的很清楚,第二个参数interfaces就是需要代理实例实现的接口列表。

  • 相关阅读:
    数据库设计
    构建评价
    Schema xds文献
    架构设计评价
    需求分析评价
    获取script的链接参数并执行
    js获取封装对象/通过id tag className
    通过css/js来固定div的位置
    nginx日志分析工具goaccesss
    如何快速安装 allure
  • 原文地址:https://www.cnblogs.com/shaohz2014/p/3723544.html
Copyright © 2020-2023  润新知