走向自动装配|第四章-Spring Boot 自动装配
文章目录
文章说明
Spring Framework 到 Spring Boot 怎么一步一步走向自动装配
- 第一章 - Spring Framework 手动装配
- 第二章 - @Enable 模块驱动
- 第三章 - Spring Boot 条件装配
- 第四章 - Spring Boot 自动装配
项目环境
- jdk 1.8
- Spring Boot 2.0.2.RELEASE
- github 地址:https://github.com/huajiexiewenfeng/deep-in-spring-boot
- 本章模块:autoconfigure
1.Spring Boot 自动装配
- 定义:基于规约大于配置原则,实现 Spring 组件自动装配的目的
- 装配:模式注解、@Enable 模块、条件装配、工厂加载机制
- 实现:激活自动装配、实现自动装配、配置自动装配实现
2.实现方法
实现的方法分为三步:
1.激活自动装配 - @EnableAutoConfiguration
2.实现自动装配 - XXXAutoConfiguration
3.配置自动装载实现 - META-INF/spring.factories
2.1 Enable 模块
@EnableHelloWorld -> @Import -> HelloWorldConfiguration -> helloWorld
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {
}
HelloWorldConfiguration 自动装配的类
public class HelloWorldConfiguration {
@Bean
public String helloWorld(){
return "hello world";
}
}
2.2 实现自动装配
- 模式注解装配
- Enable 模块装配
- 条件装配
/**
* HelloWorld 自动装配
*/
@Configuration // 模式注解装配
@EnableHelloWorld // Enable 模块装配
@ConditionalOnSystemProperty(name = "usr.name", value = "xwf") // 条件装配
public class HelloWorldAutoConfiguration {
}
2.3 配置自动装载
resources/META-INF 目录下新建 spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.huajie.deepinspringboot.configuration.HelloWorldAutoConfiguration
2.4 激活自动装配
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.huajie.deepinspringboot")
public class EnableAutoConfigurationBootstrap {
static {
System.setProperty("usr.name","xwf");
}
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableAutoConfigurationBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
String bean = context.getBean("helloWorld", String.class);
System.out.println("自动装配 hello,world bean : " + bean);
context.close();
}
}
执行结果:
自动装配 hello,world bean : hello world
如果设置 System.setProperty("usr.name","xwf1");
为其他信息,则装配失败,因为不符合条件
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'helloWorld' available
...
3.工厂加载机制
Spring 工厂加载机制
- 实现类:org.springframework.core.io.support.SpringFactoriesLoader
- 配置资源:resources/META-INF/spring.factories
3.1 装载配置核心方法
- 根据 factoryClass 类型来查找,spring.factories 中配置的相关实现类
- 通过 instantiateFactory 实例化这个类,存放到 ArrayList 集合,并返回
public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryClass, "'factoryClass' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
}
List<T> result = new ArrayList<>(factoryNames.size());
for (String factoryName : factoryNames) {
result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
}
AnnotationAwareOrderComparator.sort(result);
return result;
}
3.2 调用链路
org.springframework.boot.SpringApplication#run(java.lang.String…)
- org.springframework.boot.SpringApplication#refreshContext
- 在启动应用上下文的过程中(这个里面涉及到 Spring Framework 启动的生命周期,过程较多省略)
- org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process
- org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports
- org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations
- org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
- org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations
- org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports
3.3 调试截图
getCandidateConfigurations 中获取到 spring.factories 配置的 EnableAutoConfiguration 的所有实现
我们只需要将对应的自动装配类配置在默认的 resources/META-INF/spring.factories 中就可以了,通过这种工厂加载机制会自动获取。
4.系列总结
通过本系列这四篇章,我们可以知道,其实 Spring Boot 的自动装配特性,大部分的技术都是源自 Spring Framework,比如模式注解 @Configuration,@Enable 模块驱动,条件装配等等;Spring Boot 结合 Spring 工厂加载机制进一步将这些技术做了有机的整合,达到自动装配的效果。
在大多数场景,我们看不到 @EnableAutoConfiguration 注解的原因是,@SpringBootApplication 注解中包含了 @EnableAutoConfiguration 注解。
5.参考
- 慕课网-小马哥《Spring Boot2.0深度实践之核心技术篇》