SpringBoot的自动装配源码分析(2022.11.07)

SpringBoot的自动装配源码分析(2022.11.07)

分析的SpringBoot 版本是 **2.7.5**

1.1.0 从启动引导类中的注解开始

@SpringBootApplication // 该注解就是配置自动配置
public class DemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
    }
}

1.1.1 @interface SpringBootApplication

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration // 重点需要分析的自动配置注解
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

  	// 需要排除不进行自动配置的配置类, 例如: @SpringBootApplication(exclude = {RedisAutoConfiguration.class})
   @AliasFor(annotation = EnableAutoConfiguration.class)
   Class<?>[] exclude() default {};

    // 和上面同样作用, 是指定的类名全路径, 进行排除, 上面不在同一个类路径下就使用这个指定全路径排除
    // @SpringBootApplication(excludeName = {"org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration"})
   @AliasFor(annotation = EnableAutoConfiguration.class)
   String[] excludeName() default {};
    
	// 指定扫描的包, scanBasePackages = { "com.zhihao" }
   @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
   String[] scanBasePackages() default {};

	// 和scanBasePackages一样, 指定扫描的类所在包以及子包的所有, scanBasePackageClasses = {DemoApplication.class}
    // 本质也是和上面配置扫描当前包和子包一样, debug在AutoConfigurationPackages$Registrar#registerBeanDefinitions()
   @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
   Class<?>[] scanBasePackageClasses() default {};

   // 指定bean名称生成器
   @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
   Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

  	// 是否为配置类设置 @Bean 修饰的方法会被代理, 通过配置类调用到带有@Bean的方法时候, 本质是从IOC容器获取同一个
    // false则是@Bean 修饰的方法不会被代理, 通过配置类调用带有@Bean的方法时候是每调用一次创建一个新的,
    // 如果是在配置类内部进行调用带有@Bean会提示Method annotated with @Bean is called directly in a @Configuration where proxyBeanMethods set to false. Set proxyBeanMethods to true or use dependency injection. 
   @AliasFor(annotation = Configuration.class)
   boolean proxyBeanMethods() default true;

}

1.1.2 @interface EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 自动配置包扫描 (在refreshContext(context)刷新IOC的时候通过AutoConfigurationPackages处理)
@AutoConfigurationPackage 
// @Import导入, 需要重点分析导入的的自动配置类
@Import(AutoConfigurationImportSelector.class) 
public @interface EnableAutoConfiguration {

   /**
    *启用自动配置时可用于覆盖的环境属性。
    */
   String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

   Class<?>[] exclude() default {};

   String[] excludeName() default {};
}

AutoConfigurationImportSelector

  • 类关系图

xvwOhD.png

AutoConfigurationImportSelector.AutoConfigurationGroup#process()

@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
    // 一个判断断言
   Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
         () -> String.format("Only %s implementations are supported, got %s",
               AutoConfigurationImportSelector.class.getSimpleName(),
               deferredImportSelector.getClass().getName()));
    // 重要点获取自动配置入口
   AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
         .getAutoConfigurationEntry(annotationMetadata);
    // 然后添加到自动配置集里面
   this.autoConfigurationEntries.add(autoConfigurationEntry);
   for (String importClassName : autoConfigurationEntry.getConfigurations()) {
      this.entries.putIfAbsent(importClassName, annotationMetadata);
   }
}

下面开始通过Debug流程图方式说明

xv6YvD.png

xv645q.png

后续由 spring 的怎么将实例Bean注册到IOC容器中了, 不再继续跟踪, 想了解看之前SpringBoot启动源码分析的笔记

扩展:

@EnableConfigurationProperties(RedisProperties.class)

自动映射一个POJO到Spring Boot配置文件(默认是application.properties文件)的属性集。

可以参考: RedisAutoConfiguration 怎么使用

1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

懵懵懂懂程序员

如果节省了你的时间, 请鼓励

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

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

打赏作者

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

抵扣说明:

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

余额充值