zoukankan      html  css  js  c++  java
  • SpringBoot系列(2)——AOP-静态代理与动态代理

    摘要

    • 分别演示静态代理和动态代理

    静态代理

    手动代理

    interface

    public interface Interface_ {
        public void do();
    }
    

    需要被加强的类

    public class Object_ implements Interface_{
        @Override
        public void do() {
            System.out.println("do");
        }
    }
    

    代理类

    public class Object_Agent implements Interface_{
    
        private Object_ object_;
        public Object_Agent(Object_ object_) {
            this.object_ = object_;
        }
    
        @Override
        public  void do() {
            System.out.println("enhance");
            object_.do();
        }
        
        public static void main(String[] args) {
            Object_ object_ = new Object_();
            Object_Agent agent = new Object_Agent(object_);
            agent.do();
        }
    
    }
    

    AspectJ静态

    • 编写方式和spring aop没有区别
    • Aspectj并不是动态的在运行时生成代理类,而是在编译的时候就植入代码到class文件
    • 由于是静态织入的,所以性能相对来说比较好

    动态代理

    • JDK动态代理是基于接口的方式,代理类和目标类都实现同一个接口。
    • CGLib动态代理是代理类去继承目标类,然后重写其中目标类的方法。

    JDK动态代理

    接口

    public interface Interface_ {
        public void do();
    }
    

    需要被加强的类

    public class Object_ implements Interface_{
        @Override
        public void do() {
            System.out.println("do");
        }
    }
    

    处理器实现类

    public class InvocationHandlerImpl implements InvocationHandler{
    
        private Object object;
        public InvocationHandlerImpl(Object object)
        {
            this.object = object;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            System.out.println("enhance");
            Object object = method.invoke(object, args);
            return object;
        }
    }
    

    测试

    public class DynamicProxyDemonstration
    {
        public static void main(String[] args)
        {
            Interface_ object_ = new Object_();
            InvocationHandler handler = new InvocationHandlerImpl(object_);
            ClassLoader loader = object_.getClass().getClassLoader();
            Class[] interfaces = object_.getClass().getInterfaces();
            Interface_ object__ = (Interface_) Proxy.newProxyInstance(loader, interfaces, handler); 
            object__.do();
        }
     
    }
    

    CGlib动态代理

    POM

    <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
    </dependency>
    

    需要被加强的类

    public class Object_{
        public  void do() {
            System.out.println("do");
        }
    }
    

    方法拦截器

    public class MyMethodInterceptor implements MethodInterceptor{
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("enhance");
            Object object = proxy.invokeSuper(obj, args);
            return object;
        }  
    }
    

    测试

    public class CgLibProxy {
        public static void main(String[] args) {
            //创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
            Enhancer enhancer = new Enhancer();
            //设置目标类的字节码文件
            enhancer.setSuperclass(Object_.class);
            //设置回调函数
            enhancer.setCallback(new MyMethodInterceptor());
            //创建加运行
            Object_ proxyObject_ = (Object_)enhancer.create();
            proxyObject_.do();       
        }
    }
    

    为啥转变被CGlib

    一般写代码:

    @Autowired
    UserService userService;
    

    出错代码:

    @Autowired
    UserServiceImpl userService;
    

    启动报错

    JDK 动态代理是基于接口的,代理生成的对象只能赋值给接口变量。

    而 CGLIB 就不存在这个问题。因为 CGLIB 是通过生成子类来实现的,代理对象无论是赋值给接口还是实现类这两者都是代理对象的父类。

    总结

    • Spring5 默认aop实现为CGlib
    • JDK动态代理是基于接口的,CGlib动态代理是基于继承的

    参考

    [1].CGLib动态代理

    [2].java反射和代理

    [3].惊人!Spring5 AOP 默认使用Cglib? 从现象到源码深度分析

    本文作者: Both Savage

    本文链接: https://bothsavage.github.io/2020/12/29/SpringBoot/SpringBoot系列(2)——AOP-静态代理与动态代理/

    版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

  • 相关阅读:
    跟我一起学习ASP.NET 4.5 MVC4.0(二)(转)
    跟我一起学习ASP.NET 4.5 MVC4.0(一)(转)
    MVC3 Razor视图引擎的基础语法
    了解ASP.NET MVC几种ActionResult的本质:HttpStatusCodeResult & RedirectResult/RedirectToRouteResult
    通过一个模拟程序让你明白ASP.NET MVC是如何运行的
    ASP.NET中后台注册js脚本攻略(转)
    Python: 什么是*args和**kwargs
    配置mysql 及 设置密码
    java静态方法Static
    并发程序设计知识总结
  • 原文地址:https://www.cnblogs.com/simon-idea/p/14233337.html
Copyright © 2011-2022 走看看