第十八章 AOP底层实现原理

1.核心问题

1. AOP如何创建动态代理类
2. Spring工厂如何加工创建代理对象
    通过原始对象的id值,获得的是代理对象

2.动态代理类的创建

2.1 JDK动态代理

通过方法Proxy.newProxyInstance(ClassLoader,interfaces,InvocationHandler)创建代理对象

返回值: 动态代理对象
  • InvocationHandler
将额外功能写在InvocationHandler接口的invoke方法中,额外功能可以执行在原始方法执行之前\之后\前后\抛出异常

Object invoke(Object proxy,Method method,Object[] args)

返回值: 原始方法的返回值

参数: proxy  -->代表代理对象,将Proxy.newProxyInstance创建好的代理对象传入invoke方法,现在基本不用,可以忽略
     method  -->额外功能所增加给的那个原始方法
     args  -->原始方法的参数

原始方法的运行: method.invoke(userService,args),将运行结果作为原始方法的返回值返回
  • interfaces
原始对象实现的接口
作用: 代理类和原始类实现相同接口

userService.getClass().getInterfaces()
  • ClassLoader
类加载器的作用:

1. 通过类加载器将对应类的字节码文件加载进JVM
2. 通过类加载器创建类的Class对象,进而创建这个类的对象

过程: 编写User.java文件,编译为User.class文件,由类加载器将User.class文件加载进JVM,再由类加载器创建类的Class对象,才能创建这个类的对象

获取类加载器: JVM为每一个类的.class文件,自动分配与之对应的ClassLoader

在动态代理类的开发中,需要动态代理类,才能创建代理对象,但是,动态代理类是由动态字节码技术,也就是Proxy.newProxyInstance(interfaces,InvocationHandler),将创建的字节码直接写入JVM,没有.java文件,也没有.class文件,所以JVM不能给动态代理类分配ClassLoader,没有ClassLoader就无法创建类的Class对象,也就没办法创建类的对象,所以Proxy.newProxyInstance方法需要第三个参数,那就是类加载器

解决办法: 借用一个ClassLoader,可以是任何一个类类加载器

第十八章 AOP底层实现原理
* 编码
public class TestJDKProxy {
    public static void main(String[] args) {
        //1.创建原始对象
        UserService userService = new UserServiceImpl();
        //2.JDK创建动态代理
        //以内部类的方式实现InvocationHandler接口
        InvocationHandler handler = new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //额外方法
                System.out.println("----proxy log------");

                //原始方法运行
                Object ret = method.invoke(userService, args);
                return ret;
            }
        };
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(TestJDKProxy.class.getClassLoader(), userService.getClass().getInterfaces(), handler);
        userServiceProxy.register(new User());
        userServiceProxy.login("rad","123");
    }
}

2.2 CGlib的动态代理

CGlib创建动态代理的原理: 父子继承关系创建代理对象,原始类作为父类,代理类作为子类,这样既可以保证两者方法一致,同时也可以在代理类中提供新的实现

第十八章 AOP底层实现原理
  • CGlib编码
public class TestCGlib {
    public static void main(String[] args) {
        //1.创建原始对象
        UserService userService = new UserService();
        /*
            2.通过CGlib的方式创建动态代理对象
            和JDK创建动态代理高度一致,将实现接口变成继承父类
            Proxy.newProxyInstance(ClassLoader,interfaces,InvocationHandler)

            Enhancer.setClassLoader()
            Enhancer.setSuperClass()
            Enhancer.setCallback()  -->需要实现MethodInterceptor -->实现intercept方法(和invoke方法一致)
            enhancer.create()  --> 创建代理对象

         */
        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(TestCGlib.class.getClassLoader());
        enhancer.setSuperclass(userService.getClass());

        MethodInterceptor interceptor = new MethodInterceptor(){

            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("----log----");
                Object ret = method.invoke(userService,args);
                return ret;
            }
        };

        enhancer.setCallback(interceptor);
        UserService serviceProxy = (UserService) enhancer.create();
        serviceProxy.login("args","333");
        serviceProxy.register(new User());
    }
}
  • 总结
1. JDK创建代理对象 Proxy.newProxyInstance 通过接口实现来创建代理类
2. CGlib创建动态代理 enhancer             通过继承父类来创建代理类

3.Spring工厂如何加工原始对象成为代理对象

第十八章 AOP底层实现原理
* 编码
public class ProxyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("-----new log-----");
                Object ret = method.invoke(bean, args);
                return ret;
            }
        };
        return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),bean.getClass().getInterfaces(),handler);
    }
}

Original: https://www.cnblogs.com/suwuji/p/16514628.html
Author: 苏无及
Title: 第十八章 AOP底层实现原理

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612590/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球