springboot enable注解自动配置流程
自动配置流程
核心只有4步
@EnableCircuitBreaker
@MapperScan("com.github.chengzhx76.service.order.dao")
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
1、@Enable***一般是@import注解的简写,@import是用来导入某个bean到spring容器的
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {
}
2、selector根据条件选择需要导入的配置类。
selector是用来导入meta-inf/spring.factories配置的,继承SpringFactoryImportSelector
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableCircuitBreakerImportSelector extends
SpringFactoryImportSelector<EnableCircuitBreaker> {
@Override
protected boolean isEnabled() {
return new RelaxedPropertyResolver(getEnvironment()).getProperty(
"spring.cloud.circuit.breaker.enabled", Boolean.class, Boolean.TRUE);
}
}
3、SpringFactoriesLoader加载spring.factories配置对应的bean
selector通过父类的selectImports调用SpringFactoriesLoader加载对应的spring.factories类注册到beandefinition registry 容器实现ioc
@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() + "?");
// Find all possible auto configuration classes, filtering duplicates
List<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader
.loadFactoryNames(this.annotationClass, this.beanClassLoader)));
if (factories.isEmpty() && !hasDefaultFactory()) {
throw new IllegalStateException("Annotation @" + getSimpleName()
+ " found, but there are no implementations. Did you forget to include a starter?");
}
if (factories.size() > 1) {
// there should only ever be one DiscoveryClient, but there might be more than
// one factory
log.warn("More than one implementation " + "of @" + getSimpleName()
+ " (now relying on @Conditionals to pick one): " + factories);
}
return factories.toArray(new String[factories.size()]);
}
factories文件举例
org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration
4、实例化被加载配置的类
HystrixCircuitBreakerConfiguration这个bean就是一个配置bean,所以通过以上流程spring最终实现了自动找到配置bean的目的。
我理解是个spi插件化的过程,spring标准化了组件接入的流程。
@Configuration
public class HystrixCircuitBreakerConfiguration {
@Bean
public HystrixCommandAspect hystrixCommandAspect() {
return new HystrixCommandAspect();
}
@Bean
public HystrixShutdownHook hystrixShutdownHook() {
return new HystrixShutdownHook();
}
@Bean
public HasFeatures hystrixFeature() {
return HasFeatures.namedFeatures(new NamedFeature("Hystrix", HystrixCommandAspect.class));
}
@Configuration
@ConditionalOnProperty(value = "hystrix.stream.endpoint.enabled", matchIfMissing = true)
@ConditionalOnWebApplication
@ConditionalOnClass({ Endpoint.class, HystrixMetricsStreamServlet.class })
protected static class HystrixWebConfiguration {
@Bean
public HystrixStreamEndpoint hystrixStreamEndpoint() {
return new HystrixStreamEndpoint();
}
@Bean
public HasFeatures hystrixStreamFeature() {
return HasFeatures.namedFeature("Hystrix Stream Servlet", HystrixStreamEndpoint.class);
}
}
自定义starter
1、写bean配置类
@Configuration
@ConditionalOnClass(ExampleService.class)
//属性配置类
@EnableConfigurationProperties(ExampleServiceProperties.class)
public class ExampleAutoConfigure {
@Autowired
private ExampleServiceProperties properties;
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true")
ExampleService exampleService (){
return new ExampleService(properties.getPrefix(),properties.getSuffix());
}
}
2、写属性配置类
如果有需要配置的属性,可以加一个属性配置类,properties的属性会自动注入到配置类中。
@ConfigurationProperties("example.service")
public class ExampleServiceProperties {
private String prefix;
private String suffix;
//省略 getter setter
3、pom文件
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
4、添加spring .factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.autocinfigure.ExampleAutoConfigure
5、打包
mvn package
springboot启动原理
@springbootapplication注解
@springbootapplication包含了很多注解,如下图所示。核心在于自动配置注解@EnableAutoConfiguration,原理如上文所述
springbootappliction.run()
run方法就是初始化ioc容器和创建各种bean的过程,核心在refresh()