飞行的蜗牛

vuePress-theme-reco 极客学长    2013 - 2025
飞行的蜗牛 飞行的蜗牛

Choose mode

  • dark
  • auto
  • light
首页
分类
  • 技术杂谈
  • Database
  • Docker
  • PHP
  • 随笔杂谈
  • 前端开发
  • FunnyTools
  • Jekyll
  • 读书笔记
  • Java
  • SpringBoot
  • 区块链技术
  • IPFS
  • C/C++
  • Filecoin
  • Golang
  • Sharding-JDBC
  • 分布式存储
  • Lotus-源码系列
  • Lotus
  • 框架源码系列
  • Spring-源码系列
  • AI
  • ChatGPT
  • Stable Diffusion
  • DeepSeek-R1
  • DeepSeek-V3
标签
时间抽
关于作者
开源项目
GeekAI (opens new window)
author-avatar

极客学长

154

文章

151

标签

首页
分类
  • 技术杂谈
  • Database
  • Docker
  • PHP
  • 随笔杂谈
  • 前端开发
  • FunnyTools
  • Jekyll
  • 读书笔记
  • Java
  • SpringBoot
  • 区块链技术
  • IPFS
  • C/C++
  • Filecoin
  • Golang
  • Sharding-JDBC
  • 分布式存储
  • Lotus-源码系列
  • Lotus
  • 框架源码系列
  • Spring-源码系列
  • AI
  • ChatGPT
  • Stable Diffusion
  • DeepSeek-R1
  • DeepSeek-V3
标签
时间抽
关于作者
开源项目
GeekAI (opens new window)
  • Spring AOP 源码学习笔记

    • 01 - Spring ProxyFactory
      • 02- AOP 的启动流程
        • 03 - 匹配 Advice 的具体逻辑
          • 04 - 切面的筛选逻辑
            • 05 - 创建代理对象的过程
              • 06 - 代理对象的执行过程(核心)

              Spring AOP 源码学习笔记

              vuePress-theme-reco 极客学长    2013 - 2025

              Spring AOP 源码学习笔记


              极客学长 2022-11-16 0 Spring 源码系列

              刘慈欣 -《三体》

              弱小和无知不是生存的障碍,傲慢才是。

              # 01 - Spring ProxyFactory

              ProxyFactory 是 Spring 实现的一个代理工厂类,它也是 Spring AOP 和 Spring 事务实现的底层技术支撑。平时我们在业务代码中也可以使用它,因为用它来创建动态代理对象真实太方便了!!!只需简单的三步:

              1. 创建 ProxyFactory 对象
              2. 设置被代理的 Target
              3. 获取代理对象

              最关键的是,ProxyFactory 会自动判断你要使用 JDK 还是 CGLIB 来创建代理对象:






















               


               



              public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
                 // 如果ProxyFactory的isOptimize为true,Spring认为 cglib比jdk动态代理要快
                 // 或者isProxyTargetClass为true,
                 // 或者被代理对象没有实现接口,
                 // 或者只实现了SpringProxy这个接口
                 // 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理
              
                 // 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口
              
                 // 是不是在GraalVM虚拟机上运行
                 if (!NativeDetector.inNativeImage() &&
                       (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
              
                    Class<?> targetClass = config.getTargetClass();
                    if (targetClass == null) {
                       throw new AopConfigException("TargetSource cannot determine target class: " +
                             "Either an interface or a target is required for proxy creation.");
                    }
                    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                       return new JdkDynamicAopProxy(config);
                    }
                    return new ObjenesisCglibAopProxy(config);
                 }
                 else {
                    return new JdkDynamicAopProxy(config);
                 }
              }
              

              下面来看一个 ProxyFactory 的使用 Demo:

              // 创建被代理对象
              OrderService orderService = new OrderService();
              // 创建代理工厂
              ProxyFactory proxyFactory = new ProxyFactory();
              // 设置被代理对象
              proxyFactory.setTarget(orderService);
              // 添加一个 Advice, 实现切面方法
              proxyFactory.addAdvice(new MethodInterceptor() {
                 @Nullable
                 @Override
                 public Object invoke(@NotNull MethodInvocation invocation) throws Throwable
                 {
                    System.out.println("Around 前");
                    Object proceed = invocation.proceed();
                    System.out.println("Around 后");
                    return proceed;
                 }
              });
              // 获取代理对象
              OrderService proxy = (OrderService)proxyFactory.getProxy();
              // 代理对象执行方法
              proxy.test();
              

              有木有觉得如丝般顺滑 O(∩_∩)O 哈哈~

              # 02- AOP 的启动流程

              1. 通过 @EnableAspectJAutoProxy 注解引入 AspectJAutoProxyRegistrar 类, 从而注册一个 AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor
              2. 具体 AOP 的入口在 AnnotationWareAspectJAutoProxyCreator 的父类 AbstractAutoProxyCreator 的 postProcessAfterInitialization() 方法:




                 





                public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
                	if (bean != null) {
                		Object cacheKey = getCacheKey(bean.getClass(), beanName);
                		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                			return wrapIfNecessary(bean, beanName, cacheKey); // 包装成 AOP 代理对象
                		}
                	}
                	return bean;
                }
                
              3. 判断当前 bean 是否需要进行 AOP(是否存在匹配的 Advice),如果不需要则直接返回原对象,否则生成一个代理对象返回。

              # 03 - 匹配 Advice 的具体逻辑

              如何判断当前 Bean 是否存在匹配的 Advice 呢?具体实现过程如下:

              1. 先找到当前 Bean 容器中所有的 Advisor 类型的 Bean 对象,得到 advisors 列表

              2. 再从所有的切面中解析得到 Advisor(最终会封装成 InstantiationModelAwarePointcutAdvisorImpl 对象),将其加入 advisors 了列表中。




                 




                 



















                 



                protected List<Advisor> findCandidateAdvisors() {
                	// Add all the Spring advisors found according to superclass rules.
                	// 先找到所有Advisor类型的Bean对象
                	List<Advisor> advisors = super.findCandidateAdvisors();
                
                	// Build Advisors for all AspectJ aspects in the bean factory.
                	// 再从所有切面中解析得到Advisor对象
                	if (this.aspectJAdvisorsBuilder != null) {
                		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
                	}
                	return advisors;
                }
                
                // 具体封装 Advisor 逻辑在 ReflectiveAspectJAdvisorFactory::getAdvisor() 方法
                public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
                		int declarationOrderInAspect, String aspectName) {
                
                	validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
                
                	// 拿到当前方法所对应的Pointcut对象,但是注意:如果当前方法上是这么写的@After("pointcut()"),那么此时得到的Pointcut并没有去解析pointcut()得到对应的表达式
                	AspectJExpressionPointcut expressionPointcut = getPointcut(
                			candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
                	if (expressionPointcut == null) {
                		return null;
                	}
                
                	// expressionPointcut是pointcut
                	// candidateAdviceMethod承载了advice
                	return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                			this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
                }
                
              3. 根据当前 beanClass 类型对所有候选的 Advisor 进行筛选,筛选之后对 Advisor 进行排序。



                 

                 





                 




                protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
                	// 找到所有的Advisor
                	List<Advisor> candidateAdvisors = findCandidateAdvisors();
                	// 进行筛选
                	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
                
                	extendAdvisors(eligibleAdvisors);
                
                	// 对Advisor进行排序,按Ordered接口、@Order注解进行排序
                	if (!eligibleAdvisors.isEmpty()) {
                		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
                	}
                	return eligibleAdvisors;
                }
                

              # 04 - 切面的筛选逻辑

              具体实现在 AopUtils::canApply() 方法中

              1. 先判断类,如果类型不匹配则直接返回 false
                if (!pc.getClassFilter().matches(targetClass)) {
                	return false;
                }
                
              2. 判断方法匹配器 MethodMatcher, 遍历所有的方法,如果有一个方法匹配就返回 true
                for (Method method : methods) {
                	if (introductionAwareMethodMatcher != null ?
                			introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                			// 判断方法是否匹配
                			methodMatcher.matches(method, targetClass)) {
                		return true;
                	}
                }
                

              # 05 - 创建代理对象的过程

              1. 创建一个 ProxyFactory 对象
              2. 添加 Advisors(proxyFactory.addAdvisors(advisors)), 这里需要把匹配到的 Advice 包装成 Advisor 对象:
                • 如果本身就是 Advisor 对象,则直接强制转成 Advisor 对象并返回
                • 如果是 MethodInterceptor 对象,则包装成 DefaultPointcutAdvisor 对象。
                • 如果实现了具体的 AdvisorAdapter 接口(AfterReturningAdviceAdapter/MethodBeforeAdviceAdapter/ThrowsAdviceAdapter),将其包装成 DefaultPointcutAdvisor 对象
              3. 设置被代理对象(proxyFactory.setTargetSource(targetSource));

              # 06 - 代理对象的执行过程(核心)

              1. 使用 ProxyFactory 创建代理对象之前,先要往 ProxyFactory 中添加 Advisor 。
              2. 代理对象在执行某个方法时,先判断一下如果是 hashCode() 或者 equals() 方法则不走代理,直接调用被代理对象的方法。
              3. 如果当前执行的方法需要走代理,则会先把 ProxyFactory 中所有的 Advisor 拿出来个当前的执行的方法进行匹配。
              4. 如果匹配的结果为空,则直接调用 target 对应的方法,将匹配成功的 Advisor 都适配成 MethodInterceptor 对象(AfterReturningAdviceAdapter/MethodBeforeAdviceAdapter/ThrowsAdviceAdapter),并按照顺序放入一个列表中,形成一个调用链(chain)。
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                
              5. 将代理对象(proxy),被代理对象(target), 当前调用方法(method),代理类和调用链(chain) 封装成一个 MethodInvocation 对象。
                MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
                
              6. 调用 invocation.proceed() 方法,开始执行各个 MethodInterceptor 以及被代理对象的对应方法,具体执行逻辑在 ReflectiveMethodInvocation::proceed() 方法中。
              7. 通过递归的方式,一层一层调用对应 Advisor 中的 MethodInterceptor 中的 Invoke() 方法,需要留意的是,这里会对 Advisor 再进行一次筛选:
                InterceptorAndDynamicMethodMatcher dm =
                		(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
                // 动态匹配,根据方法参数匹配
                if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
                	return dm.interceptor.invoke(this);
                }
                else {
                	// Dynamic matching failed.
                	// Skip this interceptor and invoke the next in the chain.
                	// 不匹配则执行下一个MethodInterceptor
                	return proceed();
                }
                
              8. 直到执行完最后一个 MethodInterceptor 了,就会调用 invokeJoinpoint() 方法,从而执行被代理对象的当前方法
                // 当调用完了最后一个interceptor后就会执行被代理方法
                if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                	return invokeJoinpoint();
                }
                

              本站博文如非注明转载则均属作者原创文章,引用或转载无需申请版权或者注明出处,如需联系作者请加微信: geekmaster01

              MySQL8.0 重置密码 Spring 事务源码学习笔记