springAOP的理解

AOP是一种编程思想,面向切面编程。

 

作用?

  常见使用场景,事务的管理一般会先开启事务,然后根据事务的执行情况判断是否需要回滚操作。可以发现开启事务、回滚或者结束事务是一个经常使用的代码逻辑,但是重复写肯定是个比较麻烦的事情,一般不这么做,如果专门抽象方法来处理的话,修改或者删除的时候也会很麻烦而且会造成代码的入侵,也就是会改变原来的代码逻辑,在原来的代码上会穿插很多跟事务有关的逻辑,不好维护也不利于阅读。

  如何在不改变代码逻辑的条件下,完成在某一段代码的执行前后加上一些常用的代码逻辑(比如事务)?

  AOP切面编程解决了这个问题。

 

HOW?

  aop编程将上述需要添加的常用代码逻辑叫做通知,相当于对一段代码的增强。

  什么时候可以做代码的增强呢?aop编程认为变量的调用、构造器的调用和方法的调用的时候都可以做代码的增强(也就是增加通知),而变量、构造器、方法的调用就被称为连接点。但是springAOP只支持对方法的增强,也就是springAOP只支持方法作为连接点

  而不是所有方法都可以或者适合做代码的增强,比如被final修饰的方法。也就是切点是连接点的子集。

  增强的代码逻辑+原本的代码逻辑叫做一个切面,也就是通知+切点=切面

  引用的方式为目标对象增加新方法,大致逻辑就是我再加新建一个类(类里有我想新增的方法)将他作为目标类的对象的父类,然后同时代理目标类和新增类,也就是生成一个代理对象,代理对象有了新增类和目标类的方法。

ps 参考 https://blog.csdn.net/u010502101/article/details/76944753

  织入是个很有意思的说法,即将切面应用到目标对象并导致代理对象创建的过程。

ps:代理大致分两类:动态代理和静态代理,一般是动态代理。动态代理又有JDK和CGlib两种方式

 

一般的实现逻辑

  一般会有一个切面类,存放了一些通知的具体代码逻辑,当代码运行触发到切点(需要增强的方法),这个方法的执行就是由生成的代理对象执行,方法调用就变成了代理对象的方法调用,所以切面类一般也可以理解为代理类。

/**
     * Return a proxy. Invoked when clients obtain beans from this factory bean.
     * Create an instance of the AOP proxy to be returned by this factory.
     * The instance will be cached for a singleton, and create on each call to
     * {@code getObject()} for a proxy.
     * @return a fresh AOP proxy reflecting the current state of this factory
     */
    @Override
    public Object getObject() throws BeansException {
        initializeAdvisorChain();
        if (isSingleton()) {
            return getSingletonInstance();
        }
        else {
            if (this.targetName == null) {
                logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                        "Enable prototype proxies by setting the 'targetName' property.");
            }
            return newPrototypeInstance();
        }
    }

  上述代码是 ProxyFactoryBean的相关方法getObject方法

ps:生成的代理对象会进入容器里,singleton还是prototype?一般应该是singleton,理论上prototype也可以。prototype的对象在生成之后,spring不会再继续管理他的生命周期。

 

实现方式

  静态和动态代理。

  静态 AOP 实现, AOP 框架在编译阶段对程序源代码进行修改,生成了静态的 AOP 代理类(生成的 *.class 文件已经被改掉了,需要使用特定的编译器),比如 AspectJ。可以理解为静态就是粗暴的手动帮你修改代码

  动态 AOP 实现, AOP 框架在运行阶段对动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP。  

  Spring AOP动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

 

JDK 实现思路:

   通过实现InvocationHandlet接口和为Proxy类指定ClassLoader对象,利用反射机制获取动态代理类的构造函数,通过构造函数来创建动态代理类。

CGlib实现思路:

  通过实现MethodInterceptor接口,在运行期间通过CGlib继承要被动态代理的类重写父类的方法,实现AOP面向切面编程呢

 

优缺点对比  

  JDK动态代理是面向接口,在创建代理实现类时比CGLib要快,创建代理速度快。

  CGLib动态代理是通过字节码底层继承要代理类来实现(如果被代理类被final关键字所修饰则会失败),在创建代理这一块没有JDK动态代理快,但是运行速度比JDK动态代理要快。

springboot2.0版本是默认使用cglib方式,如需要强制修改可在配置文件中添加 spring.aop.proxy-target-class属性为false

 

AOP的通知类型及调用顺序

  

 

 

 around就是在切点的前后都有通知,around的优先级大于before和after

 

参考 https://www.cnblogs.com/godoforange/p/11587321.html

posted @ 2021-03-04 23:26  karbon  阅读(275)  评论(0)    收藏  举报