【Spring】AOP底层实现原理

【Spring】AOP底层实现原理


前言

AOP (Aspect Oriented Programing) ⾯向切⾯编程 = Spring动态代理开发
以切⾯为基本单位的程序开发,通过切⾯间的彼此协同,相互调⽤,完成程序的构建(切⾯ = 切⼊点(包、类、方法、注解) + 附加功能)

OOP (Object Oritened Programing) ⾯向对象编程 Java
以对象为基本单位的程序开发,通过对象间的彼此协同,相互调⽤,完成程序的构建

POP (Producer Oriented Programing) ⾯向过程(⽅法、函数)编程 C
以过程为基本单位的程序开发,通过过程间的彼此协同,相互调⽤,完成程序的构建


一、核心问题

1、AOP是什么(动态代理)
2、AOP如何创建动态代理类(动态字节码技术)


二、动态代理类的创建

代理创建的三要素:

1、原始对象
2、额外功能
3、代理对象和原始对象实现相同的接口(interface)

1.JDK的动态代理

Proxy.newProxyInstance⽅法参数详解

newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
//1、ClassLoader 借用的类加载器,用于创建代理类的Class对象,进而创建代理对象
//2、Class<?>[] interfaces userService.getClass().getInterfaces()
//3、InvocationHandler 用来写具体的附加功能,额外功能运行在原始方法执行前、后、前后、抛出异常

对于第三个参数需要手动实现
new InvocationHandler() {
  public Object invoke(Object proxy, Method method, Object[] args)
// 1、Proxy 可以忽略 代表的是代理对象
// 2、Method:需要加强的原始方法
// 3、args:原始方法的参数
      Object o = method.invoke(userService, args);
                             //原始对象  原始对象参数
      return o;

补充:ClassLoader 的作用
1、通过类加载器将类的字节码文件(.class)加载到JVM
2、通过类加载器创建类的Class对象,进而可以创建类的实例
如何获得类加载器:每个类的.class文件自动分配与之对应的ClassLoader(双亲委派)
思考:在动态代理的创建过程中,需要ClassLoader创建代理类的Class对象,可是动态代理类没有对应的.class文件,JVM也就不会为他分配ClassLoader,那怎么办?
答:借用一个

代码如下

public class TestJDKProxy {

    /*
        1. 借用类加载器  TestJDKProxy
                       UserServiceImpl
        2. JDK8.x前

            final UserService userService = new UserServiceImpl();
     */
    public static void main(String[] args) {
        //1 创建原始对象
        UserService userService = new UserServiceImpl();

        //2 JDK创建动态代理
        UserServiceImpl proxyInstance = (UserServiceImpl) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() {
//            ClassLoader 借用的类加载器,用于创建代理类的Class对象,进而创建代理对象
//            Class<?>[] interfaces userService.getClass().getInterfaces()
//            InvocationHandler 用来写具体的附加功能,额外功能运行在原始方法执行前、后、前后、抛出异常
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                参数:Proxy 可以忽略 代表的是代理对象
//                Method:需要加强的原始方法
//                args:原始方法的参数
                Object o = method.invoke(userService, args);
                return o;
            }
        });
        proxyInstance.login("soso","123");
        proxyInstance.register(new User());


    }
}

2.CGlib的动态代理

对于有接口实现的类我们通过JDK创建动态代理对象,那么对于没有接口实现的类,我们怎么办?

CGlib创建动态代理的原理:⽗⼦继承关系创建代理对象,原始类作为⽗类,代理类作为⼦类,这样既可以保证2者⽅法⼀致,同时在代理类中提供新的实现(额外功能+原始⽅法)

CGlib编码

public class TestCglib {
    public static void main(String[] args) {
        //1 创建原始对象
        UserService userService = new UserServiceImpl();

        /*
          2 通过cglib方式创建动态代理对象
            Proxy.newProxyInstance(classloader,interface,invocationhandler)

            Enhancer.setClassLoader()
            Enhancer.setSuperClass()
            Enhancer.setCallback();  ---> MethodInterceptor(cglib)
            Enhancer.create() ---> 代理
         */

        Enhancer enhancer = new Enhancer();

        enhancer.setClassLoader(TestCglib.class.getClassLoader());
        enhancer.setSuperclass(userService.getClass());

        MethodInterceptor interceptor = new MethodInterceptor() {
            //等同于 InvocationHandler --- invoke
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("---cglib log----");
                Object ret = method.invoke(userService, args);

                return ret;
            }
        };

        enhancer.setCallback(interceptor);

        UserService userServiceProxy = (UserService) enhancer.create();

        userServiceProxy.login("suns", "123345");
        userServiceProxy.register(new User());
    }
}

总结

  1. JDK动态代理 Proxy.newProxyInstance() 通过接⼝创建代理的实现类
  2. Cglib动态代理 Enhancer 通过继承⽗类创建的代理类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值