SpringBoot自动配置的实现原理
SpringBoot的核心就是自动配置,自动配置又是基于条件判断来配置Bean。关于自动配置的源码在spring-boot-autoconfigure-2.0.3.RELEASE.jar
回顾配置属性
在通常需要我们在property中配置信息时,通常使用@ConfigurationProperties(pefix=“前缀”)注解的方式从配置文件中获取配置,如下:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.boot.context.properties.ConfigurationProperties;
@RestController
@ConfigurationProperties(prefix = "test")
//@Component //如果这里添加了注解那么在自动配置类的时候就不用添加@enableConfigurationProperties(HelloProperties.class)注解.
public class Demo {
private String msg="default";//现在我们在配置文件写hello.msg=world,因为简单就不再展示;如果那么默认为default.
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@RequestMapping("/msg")
public Object index(){
return this.msg;
}
}
application.yml中配置信息
test:
msg: bamboo
访问url获取配置信息返回的值
http://localhost:8080/msg
如果把application.yml中的配置信息注释掉则默认使用default值,否则使用配置信息中的值,以上便是普通配置方式
解析
SpringBoot运行原理
先看@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:扫描主类所在的同级包以及下级包里的Bean
关键是@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
最关键的要属@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器:通过@Import(AutoConfigurationImportSelector.class)导入的配置功能,
AutoConfigurationImportSelector中的方法getCandidateConfigurations,得到待配置的class的类名集合,这个集合就是所有需要进行自动配置的类,而是是否配置的关键在于META-INF/spring.factories文件中是否存在该配置信息
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
打开,如下图可以看到所有需要配置的类全路径都在文件中,每行一个配置,多个类名逗号分隔,而\表示忽略换行
整个流程如上图所示