@EnableAutoConfiguration
在 @SpringBootApplication
已经有了 @EnableAutoConfiguration
对于不需要的bean
,可以在使用方用@EnableAutoConfiguration的exclude属性进行排除。
加载Bean的几种方式
1、@Configuration
用 @ComponentScan
扫描 bean
2、@Import
比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(SchedulingConfiguration.class) @Documented public @interface EnableScheduling { } @Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class SchedulingConfiguration {
@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() { return new ScheduledAnnotationBeanPostProcessor(); } }
|
SchedulingConfiguration
实际上就是一个配置文件,配置文件中有写好的bean
。
3、spring.factories
文件
需要在META-INF/spring.factories
中加入如下
1 2 3
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ gt.maxzhao.boot.xxxBean,\ gt.maxzhao.boot.xxxBeanB
|
原理就是AutoConfigurationImportSelector
搜索所有jar
中的spring.factories
文件,然后把org.springframework.boot.autoconfigure.EnableAutoConfiguration
属性的值加载为@Configuration
注解的文件。
4、自定义ImportSelector
下面来自其他人的见解(修改了部分表达与词句错误问题):
自定义ImportSelector
可以类似于AutoConfigurationImportSelector
的功能。
例如spring-cloud
下的@EnableCircuitBreaker
1 2 3 4 5 6 7 8
| @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(EnableCircuitBreakerImportSelector.class) public @interface EnableCircuitBreaker {
}
|
发现,它引入了EnableCircuitBreakerImportSelector
,它本身并没有实现ImportSelector
,而是其父类SpringFactoryImportSelector
实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Override public String[] selectImports(AnnotationMetadata metadata) { if (!isEnabled()) { return new String[0]; } AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(this.annotationClass.getName(), true));
Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is " + metadata.getClassName() + " annotated with @" + getSimpleName() + "?");
List<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader .loadFactoryNames(this.annotationClass, this.beanClassLoader)));
return factories.toArray(new String[factories.size()]); }
|
这里,我们看到,实际加载的代码是传入了this.annotationClass
,那么对于EnableCircuitBreakerImportSelector
来说,就是在spring.factories
找它的全类名:
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreakerImportSelector
对应的值。
最终在spring-cloud-netflix-core-××.jar
的spring.factories
中找到如下配置
1 2
| org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\ org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration
|
这样就完成了通过@EnableCircuitBreaker
的注解,最终加载到Hystrix
的实现HystrixCircuitBreakerConfiguration
,实现了功能定义和具体实现的分离。
本文地址: https://github.com/maxzhao-it/blog/post/63451/