简单解析 Spring boot 自动配置的流程,以 freemarker 为例
@SpringBootApplication
创建 Application 时的注解,该注解定义了 @EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Configuration
@EnableAutoConfiguration
@ComponentScan
@EnableAutoConfiguration
该注解导入 EnableAutoConfigurationImportSelector.class
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)EnableAutoConfigurationImportSelector.class
EnableAutoConfigurationImportSelector.class 类将查找 spring-boot-autoconfigure 包 META-INF 文件夹下的 spring.factories
找到对应的 Key (org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\) 值后,加载该 key 值对应的类进行自动配置
FreeMarkerAutoConfiguration.class
@Configuration
@ConditionalOnClass({ freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class })
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(FreeMarkerProperties.class)@Configuration:表示一个 Spring javaConfig 配置类,取代 xml 方式,比如:<bean id="freemarkerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">@ConditionalOnClass :指定的类在类路径下存在时,该类才会加载@AutoConfigureAfter :指定类加载之后,该类才会加载
@EnableConfigurationProperties :引入一个配置属性对象
按这个套路实现一个自定义的自动配置
WeatherConfigurer
// Weather 组件的配置类,模拟 freemarker.jar 包中的 FreeMarkerConfigurer
public class WeatherConfigurer {
private String temperature;
private boolean isWarnning;
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public boolean isWarnning() {
return isWarnning;
}
public void setWarnning(boolean isWarnning) {
this.isWarnning = isWarnning;
}
}WeatherProperties
// JavaConfig, 可以用 application.properties 中的配置进行覆盖
@ConfigurationProperties(prefix = "weather")
public class WeatherProperties {
private String temperature = "30`C";
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
}
WeatherAutoConfiguration
// 自动配置类,将配置 WeatherConfig 的值
@Configuration
@ConditionalOnClass(WeatherConfigurer.class)
@EnableConfigurationProperties(WeatherProperties.class)
public class WeatherAutoConfiguration {
@Autowired
private WeatherProperties properties;
// 该注解相当于原来 xml 中 配置 <bean id="xxx" class="xxx">
// 其返回值将作为一个 bean 定义并注册到 Spring 的 IoC 容器, 所以必须有返回值
@Bean
// 核心:如果用户没有自定义该 Bean, Spring 才会自动配置这个新的 Bean
// 注意:是定义 WeatherConfigurer 的 Bean, 即@Bean, 而不是 new WeatherConfigurer(), 不要混淆了
@ConditionalOnMissingBean(WeatherConfigurer.class)
// @ConditionalOnMissingBean(name = "weatherConfigurer") // 另一种写法,匹配的 Bean name
public WeatherConfigurer weatherConfigurer() {
WeatherConfigurer configurer = new WeatherConfigurer();
configurer.setTemperature(properties.getTemperature()); // 使用 JavaConfig , 可用 application.properties 覆蓋配置
return configurer;
}
}
Application 测试自动配置
@RestController
@SpringBootApplication
public class Application {
// 注入 WeatherAutoConfiguration 中创建的 @Bean WeatherConfigurer
@Autowired
private WeatherConfigurer config;
@RequestMapping("/")
public String home() {
return config.getTemperature();
}
public static void main(String[] args) {
// 打印 Spring 容器中创建的 Bean
ApplicationContext ctx = SpringApplication.run(Application.class, args);
String[] beanNames = ctx.getBeanDefinitionNames();
System.out.println("bean count: " + beanNames.length);
for (String name : beanNames) {
System.out.println(name);
}
}
}运行后,查看结果是否为自动配置的值 30`C
然后通过 application.properties 配置项
weather.temperature=40`C
再运行,查看结果是否改变
357

被折叠的 条评论
为什么被折叠?



