@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/