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
- 类关系图
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流程图方式说明
后续由 spring 的怎么将实例Bean注册到IOC容器中了, 不再继续跟踪, 想了解看之前SpringBoot启动源码分析的笔记
扩展:
@EnableConfigurationProperties(RedisProperties.class)
自动映射一个POJO到Spring Boot配置文件(默认是application.properties文件)的属性集。
可以参考:
RedisAutoConfiguration
怎么使用
1