从@SpringBootApplication 开始
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
.......
}
@SpringBootApplication 上的 @EnableAutoConfiguration
从这个注解字面上的意思就是能够自动化配置,springboot很多注解都是以enable开头的,他们的实现都差不多
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
......
}
@import 很重要,就是实现enable相关注解的关键 所以springboot实现自动化装配的第一步就是@import (需要了解 ConfigurationClassPostProcessor 这个类)
@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector#selectImports 方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//这个调用一层套一层,简单的说就是从spring.factories中获得
//key 为 EnableAutoConfiguration这个注解的全类名,spring会调用
//本方法,将返回去的类进行解析实例化并且注册到spring容器中
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
比如说EmbeddedWebServerFactoryCustomizerAutoConfiguration 这个类就会被解析出来
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
...........
}
可以看到上面有个很重要的注解 @EnableConfigurationProperties(ServerProperties.class)
@EnableConfigurationProperties(ServerProperties.class) 这句代码做了什么
//又是import 可见 这个注解多么重要
@Import(EnableConfigurationPropertiesImportSelector.class)
public @interface EnableConfigurationProperties {
....
}
EnableConfigurationPropertiesImportSelector 这个类做了什么
private static final String[] IMPORTS = {
ConfigurationPropertiesBeanRegistrar.class.getName(),
ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() };
@Override
public String[] selectImports(AnnotationMetadata metadata) {
//返回 ConfigurationPropertiesBeanRegistrar 和 //ConfigurationPropertiesBindingPostProcessorRegistrar 让spring解析注册到spring容器中
return IMPORTS;
}
ConfigurationPropertiesBeanRegistrar
public static class ConfigurationPropertiesBeanRegistrar
implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//在解析 ConfigurationPropertiesBeanRegistrar 的时候会调用这个方法
//这个方法干嘛的?
//会拿到@EnableConfigurationProperties(ServerProperties.class) 注解上的的value,比如这个 ServerProperties 然后注册到 spring容器中,所以ServerProperties就被spring管理起来了
getTypes(metadata).forEach((type) -> register(registry,
(ConfigurableListableBeanFactory) registry, type));
}
}
ServerProperties 配置类
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
/**
* Server HTTP port.
*/
private Integer port;
/**
* Network address to which the server should bind.
*/
private InetAddress address;
.......
}
这个类很熟悉,就是我们在application.yml 中使用到的,server.prot等等,到了这一步,spring已经把ServerProperties注册成beandefinition,但是什么时候把这个配置类的属性从application.yml中获取到。 还有个类没有说到 ConfigurationPropertiesBindingPostProcessorRegistrar (上文有)
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
//判断spring中有没有
### ConfigurationPropertiesBindingPostProcessor这个类
//如果没有就往 spring注册
//(这个方法会被反复执行,但是只会注册一次,不知道为啥spring在这边没有优化)
if (!registry.containsBeanDefinition(
ConfigurationPropertiesBindingPostProcessor.BEAN_NAME)) {
registerConfigurationPropertiesBindingPostProcessor(registry);
registerConfigurationBeanFactoryMetadata(registry);
}
}
ConfigurationPropertiesBindingPostProcessor 有什么作用
这就涉及到spring bena的生成 这个类实现了BeanPostProcessor 是spring的一种后置处理器。
//在 bean 实例化之后,初始化之前执行
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
ConfigurationProperties annotation = getAnnotation(bean, beanName,
ConfigurationProperties.class);
if (annotation != null) {
// 执行绑定逻辑,将配置跟bean中的属性绑定,完成自动化装配
bind(bean, beanName, annotation);
}
return bean;
}
一层套一层…………