Spring篇(3)--Spring Aop基本流程原理

本文介绍了Spring AOP的基本概念及其实现原理,重点解析了AOP在Spring中的代理对象创建过程,包括Bean的初始化前后所触发的一系列操作,以及如何通过BeanPostProcessor创建代理Bean。
部署运行你感兴趣的模型镜像

一、Spring AOP是什么


  • AOP:面向切面,是一种编程思想,OOP的延续。
  • 将系统中非核心的业务提取出来,进行单独处理。比如事务、日志和安全等。这个简单来说就是可以在一段程序之前或者之后做一些事。

二、代理对象的创建过程:


AbstractAutowireCapableBeanFactory#initializeBean

protectedObjectinitializeBean(StringbeanName,Objectbean,@NullableRootBeanDefinitionmbd){
    if(System.getSecurityManager()!=null){
        AccessController.doPrivileged((PrivilegedAction<Object>)()->{
            invokeAwareMethods(beanName,bean);
            return null;
        },getAccessControlContext());
    }
    else{
        invokeAwareMethods(beanName,bean);
    }

    ObjectwrappedBean=bean;
    if(mbd==null||!mbd.isSynthetic()){
        // 执⾏所有的BeanPostProcessor#postProcessBeforeInitialization 初始化之前
的处理器⽅法
        wrappedBean=applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
    }

    try{
        // 这⾥就开始执⾏afterPropertiesSet(实现了InitializingBean接⼝)⽅法和
        initMethod
        invokeInitMethods(beanName,wrappedBean,mbd);
    }
    catch(Throwableex){
        thrownewBeanCreationException((mbd!=null?            mbd.getResourceDescription():null),beanName,"Invocationofinitmethodfailed",ex);
    }
    if(mbd==null||!mbd.isSynthetic()){
        // 整个Bean初始化完成,执⾏后置处理器⽅法
        wrappedBean=applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName);
    }

    return wrappedBean;
}

可以看到有初始化前执行的方法、初始化时执行的方法、初始化之后执行的方法,我们从初始化之后执行的方法入手。

三、applyBeanPostProcessorsAfterInitialization


applyBeanPostProcessorsAfterInitialization()方法的流程如下:

简要流程:

详细流程:

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
->AbstractAutoProxyCreator#postProcessAfterInitialization

(1)创建代理Bean:applyBeanPostProcessorsAfterInitialization中会检查下该类是否已经暴露过了(可能已经创建了,⽐如A依赖B时,创建A时候,就会先去创建B。当真正需要创建B时,就没必要再代理⼀次已经代理过的对象),避免重复创建。

->AbstractAutoProxyCreator#wrapIfNecessary

(2)获取适用于当前类的Advisor:得到所有候选Advisor(切点),对Advisors和bean的⽅法双层遍历匹配,最终得到⼀个List<Advisor>,即specificInterceptors,指对这个bean进行操作的切点

->AbstractAutoProxyCreator#createProxy

(3)创建代理:

A、创建代理的⼯作交给ProxyFactory

B、把指定和通⽤拦截对象合并, 并都适配成Advisor

C、上⾯准备做完就开始创建代理

->proxyFactory.getProxy()

(4)依据是否是接口,判断使用jdk还是cglib:⽤ProxyFactory创建AopProxy, 然后⽤AopProxy创建Proxy, 所以这⾥重要的是看获取的AopProxy对象是什么,然后进去看怎么创建动态代理, 提供了两种:jdk proxy, cglib

四、Aop的jdk和cglib怎么实现?有什么工作区别


4-1)JDK 动态代理

        4-1-1)基于接口:JDK 动态代理要求目标类必须实现至少一个接口。

        4-1-2)代理对象生成:在运行时,通过 java.lang.reflect.Proxy 类动态生成代理类。

代理类会实现目标类的接口,并重写接口中的方法。

        通过 InvocationHandler 接口的 invoke 方法实现增强逻辑。

4-2)CGLIB 代理

        4-2-1)基于继承:CGLIB 通过生成目标类的子类来实现代理。

        4-2-2)代理对象生成:使用 ASM 字节码操作框架动态生成目标类的子类。重写父类方法,并在方法中插入增强逻辑。代理类会覆盖父类的非 final 方法。

4-3)Spring 中如何选择代理方式

        4-3-1)默认行为:

        如果目标类实现了接口,Spring 默认使用 JDK 动态代理。

        如果目标类没有实现接口,Spring 使用 CGLIB 代理。

        4-3-2)强制使用 CGLIB:

@EnableAspectJAutoProxy(proxyTargetClass = true) // 强制使用 CGLIB

        4-3-3)性能考量:

在低版本 Spring 中,CGLIB 生成代理较慢,但调用更快;JDK 代理生成快,调用慢。

在高版本 Spring 和 JDK 中,两者性能差距已不明显。

五、Spring aop在什么场景下会失效


AOP失效的场景:

        1)静态方法调用:静态方法不属于对象,因此无法通过代理对象调用,AOP无法拦截。Spring AOP 基于动态代理,无法拦截静态方法。

        2)final方法:final方法无法被覆盖,因此无法通过子类化实现代理,AOP无法拦截。CGLIB 代理通过生成子类实现,无法覆盖私有方法和 final 方法。

        3)私有方法调用:私有方法只能在类内部调用,无法通过代理对象调用,AOP不会生效。

        4)自调用:当一个方法在同一个类中自调用时,AOP同样不会生效。Spring AOP 通过代理对象调用方法,而内部调用绕过代理直接访问目标对象。Spring AOP 通过代理对象调用方法,而内部调用绕过代理直接访问目标对象。

备注:

1)如何利用aop切面实现多数据源切换

        1-1)配置多数据源:application.yml 中定义多个数据源(如主库、从库)

        1-2)定义动态数据源路由类:继承 AbstractRoutingDataSource,通过 ThreadLocal 保存当前线程的数据源标识:

        1-3)定义数据源切换注解:创建 @DataSource 注解,用于标记方法或类应使用的数据源

        1-4)配置数据源 Bean 和动态路由:在 Spring 配置类中注册数据源,并将动态路由设为默认数据源

        1-5)创建 AOP 切面实现数据源切换:通过切面拦截 @DataSource 注解,动态切换数据源

        1-6)使用:在 Service 方法上标注 @DataSource,指定数据源

2)Spring的上下文怎么存储?

        2-1)Bean定义:通过 BeanDefinitionRegistry 存储为Map。

        2-2)Bean实例:单例Bean缓存于 ConcurrentHashMap,原型Bean每次重新创建。

        2-3)依赖管理:三级缓存解决循环依赖。

        2-4)环境配置Environment 管理多属性源。

        2-5)AOP代理:代理对象覆盖原始Bean存储。

        2-6)层级结构:父子上下文独立存储,子可访问父。

 更多内容:

Spring篇(1)--SpringBoot是什么?原理是怎么样的?

Spring篇(2)--Spring IOC基本流程原理

Spring篇(3)--Spring Aop基本流程原理

Spring篇(4-1)--Spring Bean 是什么及其生命周期阶段

Spring篇(4-2)--Spring BeanFactory与FactoryBean 区别

Spring篇(5-1)--Spring事务流程原理

Spring篇(5-2)--Spring事务传播行为

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sun cat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值