SpringBoot启动流程分析知识点--AOP(一)

SpringBoot启动流程分析知识点–AOP(一)

一、概述

源码基于SpringBoot 2.7.xx版本

官网:SpringBoot–aop

前置知识点–SpringBoot启动流程分析6–run方法之refreshContext()方法
前置知识点–SpringBoot扩展点–BeanPostProcessor

1.1 简介

AOP(Aspect Oriented Programming)是基于切面编程的,可无侵入的在原本功能的切面层添加自定义代码,一般用于日志收集、权限认证等场景。

  1. Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理。
  2. SpringBoot 2.x 开始,通过自动装配类AopAutoConfiguration.AspectJAutoProxyingConfiguration.CglibAutoProxyConfiguration,
    默认使用 CGLIB 动态代理。
  3. 在 SpringBoot 2.x 中,如果需要默认使用 JDK 动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改,
    proxyTargetClass配置已无效。

1.2 分类

  • AspectJAwareAdvisorAutoProxyCreator:当使用xml进行定义切面时会注入此类
  • AnnotationAwareAspectJAutoProxyCreator:当使用@EnableAspectJAutoProxy注解方式来定义切面时会注入此类(
    自动装配AopAutoConfiguration)
  • InfrastructureAdvisorAutoProxyCreator:当使用@EnableTransactionManagement会注入此类(
    自动装配TransactionAutoConfiguration)

1.3 AOP自动装配概览

  • AopAutoConfiguration
    • CglibAutoProxyConfiguration
    • @EnableAspectJAutoProxy
      • AspectJAutoProxyRegistrar
        • AnnotationAwareAspectJAutoProxyCreator

二、自动装配详解

2.1 AopAutoConfiguration自动装配

AopAutoConfiguration


@AutoConfiguration
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
   

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(Advice.class)
    static class AspectJAutoProxyingConfiguration {
   

        @Configuration(proxyBeanMethods = false)
        @EnableAspectJAutoProxy(proxyTargetClass = false)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
        static class JdkDynamicAutoProxyConfiguration {
   

        }

        @Configuration(proxyBeanMethods = false)
        @EnableAspectJAutoProxy(proxyTargetClass = true)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
                matchIfMissing = true)
        static class CglibAutoProxyConfiguration {
   

        }

    }
}

AspectJAutoProxyRegistrar

AopAutoConfiguration --> @EnableAspectJAutoProxy --> AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   

    /**
     * 注册、升级和配置自动代理创建器依赖对应的proxyTargetClass属性在解析@Configuration类
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   

        // 注入AnnotationAwareAspectJAutoProxyCreator
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
   
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
   
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
   
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }

}

注:

  1. AspectJAutoProxyRegistrar 注入了 AnnotationAwareAspectJAutoProxyCreator;
  2. AnnotationAwareAspectJAutoProxyCreator 是一个 SmartInstantiationAwareBeanPostProcessor,调用时机在Bean初始化之后。

2.2 AnnotationAwareAspectJAutoProxyCreator 使用

调用时机:
DefaultListableBeanFactory.preInstantiateSingletons() --> getBean() --> doGetBean() --> createBean() -->
doCreateBean() --> initializeBean() --> applyBeanPostProcessorsAfterInitialization()执行Bean的后置处理器

2.2.1 applyBeanPostProcessorsAfterInitialization()

调到父类的postProcessAfterInitialization()方法中,然后在wrapIfNecessary()方法中查找Advisor并创建代理类!

AnnotationAwareAspectJAutoProxyCreator --> AbstractAutoProxyCreator

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
   

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   
        if (bean != null) {
   
            // 获取当前bean的key:如果beanName不为空,则以beanName为key,如果为FactoryBean类型,
            // 前面还会添加&符号,如果beanName为空,则以当前bean对应的class为key
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // 判断当前bean是否正在被代理,如果正在被代理则不进行封装
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
   
                // 如果它需要被代理,则需要封装指定的bean
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
   
            return bean;
        }
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
   
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
   
            this
  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

fanderboy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值