Spring AOP编程

AOP编程

1.AOP概念

AOP(Aspect Oriented Programing):面向切面编程,以切面为基本单位的程序开发,通过切面见得彼此协同、相互调用、完成程序的构建。

  • 面向切面编程 = Spring的动态代理开发
  • 切面 = 切入点+ 额外功能

OOP(Object Oriented Programing):面向对象编程,以对象为基本单位的程序开发,通过对象见得彼此协同,相互调用,完成程序的构建。

POP(Producer Oriented Programing):面向过程(方法、函数)编程,以过程为及本单位的程序开发,通过过程间的的彼此协同,相互调用,完成程序的构建。

总之:

  1. AOP的本质:就是Spring的动态代理,通过代理类为原始类增加额外功能。
  2. 好处:有利于原始类的维护
  3. 注意:AOP编程不可能取代OOP,AOP编程时OOP的补充,因为面向切面编程的前提也是要有对象。

2. AOP的开发步骤

因为AOP编程就是Spring的动态代理,所以AOP编程的开发步骤与Spring动态代理开发步骤一样:

  1. 原始对象
  2. 额外功能(MethodInterceptor)
  3. 切入点
  4. 组装切面(额外功能+切入点)

4. AOP的底层实现原理

1. 核心问题
1.AOP如何创建动态代理类?
答:动态字节码结束
2. Spring工厂如何进行加工创建代理对象?
答:通过原始对象的id值,获得的是代理对象
2. 动态代理类的创建

创建代理对象的三要素:

  1. 原始对象
  2. 额外功能
  3. 原始对象与代理对象实现相同的接口
2.1JDK的动态代理
  1. Proxy.newProxyInstance方法参数详解

    在这里插入图片描述

    在这里插入图片描述

  • newProxyInstance方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

ClassLoader:动态代理类没有对应的.class文件,JVM也就不会为其分配ClassLoader,所以需要借用一个ClassLoader,用来创建代理类的Class对象,进而可以创建代理对象。

interfaces:原始对象所实现的接口(代理三要素第3点)

InvocationHandler:用于书写额外功能(代理三要素第2点)

InvocationHandler invocationHandler = new InvocationHandler() {
            /**
             * @param proxy 代理对象(可以忽略掉)
             * @param method 额外功能所增加给的那个原始方法
             * @param args 原始方法的参数
             * @return 原始方法的返回值
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        };
  • 类加载器

    1. 类加载器作用:

      1. 通过类加载器把对应类的字节码文件加载到JVM中
      2. 通过类加载器创建类的Class对象,进而创建这个类的对象
      
    2. 如何获得类加载器

      每一个类的.class文件自动分配与之对应的ClassLoader
      

      对于动态代理而言,没有静态代理那样手写一个代理类,所以动态代理类也就没有.class文件,JVM就不会为其分配类加载器。虽然通过动态字节码技术可以创建字节码直接写入到JVM中,但是必须通过类加载器才能创建类的Class对象,所以需要一个ClassLoader,才能创建这个类的对象。

  1. JDK动态代理编码

    public class TestJDKProxy {
        public static void main(String[] args) {
            //1. 原始对象
            UserService userService = new UserServiceImpl();
    
            //2. jdk创建动态代理
            InvocationHandler invocationHandler = new InvocationHandler() {
                /**
                 * @param proxy 代理对象(可以忽略掉)
                 * @param method 额外功能所增加给的那个原始方法
                 * @param args 原始方法的参数
                 * @return 原始方法的返回值
                 * @throws Throwable
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("---jdk log---");
                    Object ret = method.invoke(userService, args);
                    System.out.println("---jdk log---");
                    return ret;
                }
            };
            //获取代理对象
            UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                    userService.getClass().getInterfaces(), invocationHandler);
            userService.login("zhangsan", "法外狂徒");
            userService.register(new User());
    
            userServiceProxy.login("zhangsan", "法外狂徒");
            userServiceProxy.register(new User());
        }
    }
    
2.2 CGlib的动态代理

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

有时候原始类没有实现任何接口,要想代理类与原始类拥有相同的接口 ,就可以通过继承实现。

  1. CGlib与jdk动态代理区别

    image-20220417210208009

  2. CGlib编码

    public class TestCGlib {
    
        public static void main(String[] args) {
            //1. 创建原始对象
            UserService userService = new UserService();
            //2. CGlib动态代理
            Enhancer enhancer = new Enhancer();
            enhancer.setClassLoader(TestCGlib.class.getClassLoader());
            //没有与原始类实现相同接口,而是采用继承实现,所以与jdk动态代理不一样,不是设置原始类所有接口,而是设置原始类类型
            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("---cglib log---");
                    Object ret = method.invoke(userService, args);
                    System.out.println("---cglib log---");
                    return ret;
                }
            };
            enhancer.setCallback(interceptor);
            UserService userServiceProxy = (UserService) enhancer.create();
            userServiceProxy.login("zhangsan", "zhangsan");
            userServiceProxy.register(new User());
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值