Springboot自动装配
springboot启动时我们常见的就是一个注解@SpringBootApplication 和 SpringApplication的run方法,前面介绍过run(https://www.jianshu.com/p/90ebeec86f64),今天详细看一下@SpringBootApplication。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
@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 {
主要包含@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan
首先@ComponentScan,默认扫描的是与该类同级的类或者同级包下的所有类
其次@SpringBootConfiguration,只是封装了@Configuration,把启动类指定为一个javaConfig(会在容器刷新中的invokeBeanFactoryPostProcessors里进行解析执行)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
最后@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
@EnableAutoConfiguration里面有两个主要的注解@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)。
@AutoConfigurationPackage,该注解的作用是添加该注解的类所在的package(启动类所在路径) 作为 自动配置package 进行管理。
@Import(AutoConfigurationImportSelector.class),看一下后面它注册到容器中的bean AutoConfigurationImportSelector.class。
public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered {
//省略。。。。。
其中DeferredImportSelector extends ImportSelector,所以会执行到selectImports,DeferredImportSelector 和 ImportSelector的区别在于DeferredImportSelector为延时加载,等configure都加载完了才开始加载
看一下AutoConfigurationImportSelector里的selectImports
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//判断是否需要自动装配
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//从META-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相关属性
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//读取META-INF/spring.factories下的EnableAutoConfiguration的配置(这里用到了SpringFactoriesLoader,和启动过程中加载spring.factories中的初始化器和监听器是同一个)
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//排除与过滤
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
//让所有配置在META-INF/spring.factories下的AutoConfigurationImportListener执行AutoConfigurationImportEvent事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
上面这些过程只是确定了需要自定装配的类,真正开始处理是在容器刷新中的invokeBeanFactoryPostProcessors方法里,里面用了ConfigurationClassPostProcessor这个后置处理来处理并且用相应的解析器来解析@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理),具体可参考https://www.jianshu.com/p/ab0b7df24c01
另外,每个需要自动装配的类都可以根据条件判断是否进行装配@ConditionalXXX,举例mq
@Configuration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
网友评论