AOP,JDK动态代理和Cglib代理实现

AOP

主要用途:

将日志记录、性能统计、安全控制、事务处理、异常处理等代码从业务逻辑代码中剥离出来,通过对这些行为的分离,可以将它们独立到非业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

主要概念:

Aspect(切面):类似于Java中的类声明,在Aspect中会包含着一些Pointcut以及相应的Advice

Joint point(连接点):表示在程序中明确定义的点,典型的包括构造方法调用、字段的设置和获取、方法的调用、方法的执行、异常处理执行、类的初始化,它自身还可以嵌套其它 joint point

Pointcut(切点):提供一组规则来匹配joint point,这些joint point或通过逻辑关系匹配,或是通过通配、正则表达式等方式匹配,它定义了相应的Advice将要发生的地方

Advice(增强):Advice定义了被PointCut匹配的Joint Point具体要做的操作,通过before、after、around来区别是在每个joint point之前、之后还是前后都要执行的代码

Target(目标对象):织入Advice的目标对象

Weaving(织入):将Aspect和其他对象连接起来, 并创建 Adviced object 的过程

JDK动态代理实现

  1. 创建调用处理器, 调用新建proxy对象中的方法时, 都会调用该接口中的invoke方法

  2. 获取实现指定接口的代理类Class对象

  3. 通过反射创建一个代理类对象, InvocationHandler是传入构造方法的参数

     final UserDao userDaoImpl = new UserDaoImpl();
     final Aspect aspect = new Aspect();
    
     // 1. 创建调用处理器, 调用新建proxy对象中的方法时, 都会调用该接口中的invoke方法
     /*
      * InvocationHandler是被代理对象的调用处理器实现的接口, 每个代理对象都有一个关联的调用处理器, 当代理对象的一个方法被调用时, 该方法调用会被编码并转换为对它的调用处理器的invoke()方法的调用
      *     Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance,
      *     the method invocation is encoded and dispatched to the invoke method of its invocation handler.
      */
     InvocationHandler handler = new InvocationHandler() {
         @Override
         public Object invoke(Object proxy/*被调用代理对象*/, Method method/*代理对象中被调用的方法*/, Object[] args/*调用方法时的参数*/) throws Throwable {
             aspect.beforeExecute(); // 调用被代理对象方法前执行切面类中的Advice
             Object obj = method.invoke(userDaoImpl, args); // 最终的方法调用还是由被代理对象userDaoImpl执行
             aspect.afterExecute(); // 调用被代理对象方法后执行切面类中的Advice
    
             return obj;
         }
     };
    
     // 2. 获取实现指定接口的代理类的Class对象
     Class proxy = Proxy.getProxyClass(Factory.class.getClassLoader(), UserDao.class);
    
     // 3. 通过反射创建一个代理类对象, InvocationHandler是传入构造方法的参数
     // UserDao userDaoProxy = (UserDao) proxy.getConstructor(new Class[]{InvocationHandler.class}).newInstance(new Object[]{handler}); // 可变长形参可以传入一个数组
     UserDao userDaoProxy = (UserDao) proxy.getConstructor(InvocationHandler.class).newInstance(handler);
    
    
     return userDaoProxy;
    
     /*
      * 以上操作可以用Proxy.newProxyInstance()方法一步完成:
      *
      * Object proxyObject = Proxy.newProxyInstance(
      *                 Factory.class.getClassLoader(), // 类加载器, 为null表示使用默认的类加载器
      *                 new Class[]{UserDao.class}, // 代理类和被代理类都需要实现的接口, 为可变长参数
      *                 new InvocationHandler() {  // 调用处理器, 使用新建的proxy对象调用方法的时, 都会调用该接口中的invoke方法
      *                     @Override
      *                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      *                         aspect.beforeExecute();
      *                         Object obj = method.invoke(userDao, args);
      *                         aspect.afterExecute();
      *
      *                         return obj;
      *                     }
      *                 });
      *
      *         return (UserDao) proxyObject;
      */
    

Cglib代理实现:

  1. 创建方法拦截器, 调用目标方法时CGLib会回调MethodInterceptor中的 intercept() 进行拦截, 在该方法中实现增强

  2. 使用Enhancer为被代理类创建子类, 设置回调方法拦截器

  3. 创建代理类对象

     final UserDaoImpl userDaoImpl = new UserDaoImpl();
     final Aspect aspect = new Aspect();
     // 1. 创建方法拦截器, 调用目标方法时CGLib会回调MethodInterceptor中的 intercept() 进行拦截, 在该方法中实现增强
     MethodInterceptor interceptor = new MethodInterceptor() {
         @Override
         public Object intercept(Object object/*CGLib生成的代理类实例*/, Method method/*被调用代理对象方法*/,
                                 Object[] args/*参数列表*/, MethodProxy methodProxy/*代理类对方法的代理引用*/) throws Throwable {
             aspect.beforeExecute(); // 调用被代理对象方法前执行切面类中的Advice
             Object obj = method.invoke(userDaoImpl, args);  // 最终的方法调用由被代理对象userDaoImpl执行
             aspect.afterExecute();  // 调用被代理对象方法后执行切面类中的Advice
    
             return obj;
         }
     };
    
     // 2. 使用Enhancer为被代理类创建子类, 设置回调方法拦截器
     Enhancer enhancer = new Enhancer();
     enhancer.setSuperclass(UserDaoImpl.class); // Enhancer是CGLib中的一个字节码增强器, 可以为被代理类创建子类
     enhancer.setCallback(interceptor);
    
     // 3. 创建代理类对象
     Object proxyObject = enhancer.create();
    
     return (UserDaoImpl) proxyObject;
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值