SpringBoot的核心就是自动配置,自动配置又是基于条件判断来配置Bean。关于自动配置的源码在spring-boot-autoconfigure-2.0.3.RELEASE.jar
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 配置扫描包的路径
关键是@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(AutoConfigurationImportSelector.class)
这个类AutoConfigurationImportSelector中的方法getCandidateConfigurations,得到待配置的class的类名集合,这个集合就是所有需要进行自动配置的类:
protected List 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;
}
,是否配置的关键在于META-INF/spring.factories文件中是否存在该配置信息
所以需要自定义自己的META-INF/spring.factories。
开始动手
需要准备三个类:
YhmTomcatServer.java 需要被实例化的服务类
YhmTomcatServerProperties.java 配置信息属性类
YhmTomcatServiceAutoConfiguration.java 自动配置类
YhmTomcatServer.java如下
package com.yhm.springboottest1.autoconfiguration;
public class YhmTomcatServer {
private Integer port;
private String webRoot;
public String run(){
return "Startup Yhm Tomcat at port=" + port + ",webRoot=" + webRoot;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getWebRoot() {
return webRoot;
}
public void setWebRoot(String webRoot) {
this.webRoot = webRoot;
}
}
YhmTomcatServerProperties类如下:
package com.yhm.springboottest1.autoconfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = “yhm.tomcat”)
public class YhmTomcatServerProperties {
private static final String WEB_ROOT = “yhmRoot”;
private static final Integer PORT = 8080;
private String webRoot = WEB_ROOT;
private Integer port = PORT;
public String getWebRoot() {
return webRoot;
}
public void setWebRoot(String webRoot) {
this.webRoot = webRoot;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
}
YhmTomcatServiceAutoConfiguration.java类如下:
/**
- Author: huiming.yin
- Time: 2022/01/14
- Describe: 自动配置类
- 根据条件判断是否要自动配置,创建Bean
*/
@Configuration
@EnableConfigurationProperties(YhmTomcatServerProperties.class)//声明开启属性注入YhmTomcatServerProperties
@ConditionalOnClass(YhmTomcatServer.class)//判断YhmTomcatServer这个类在类路径中是否存在,只有存在时才符合条件
@ConditionalOnProperty(prefix = “yhm.tomcat”, value = “enabled”,matchIfMissing = true)
public class YhmTomcatServiceAutoConfiguration {
@Autowired
private YhmTomcatServerProperties yhmTomcatServerProperties;
@Bean(name = “yhmTomcatServer”)
@ConditionalOnMissingBean(YhmTomcatServer.class)//当容器中没有这个Bean时(YhmTomcatServer)就自动配置这个Bean,Bean的参数来自于YhmTomcatServerProperties
public YhmTomcatServer mistraService(){
YhmTomcatServer yhmTomcatServer = new YhmTomcatServer();
yhmTomcatServer.setWebRoot(yhmTomcatServerProperties.getWebRoot());
yhmTomcatServer.setPort(yhmTomcatServerProperties.getPort());
return yhmTomcatServer;
}
}
再创建如下路径文件src/main/resources/META-INF/spring.factories,内容如下
Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.yhm.springboottest1.autoconfiguration.YhmTomcatServiceAutoConfiguration
创建一个controller类,自动Autowired上面自动配置的类YhmTomcatServer
/**
*
- @author huiming.yin
- @since 2021-10-14
*/
@RestController
@RequestMapping("/")
public class YhmTomcatController {
@Autowired
private YhmTomcatServer yhmTomcatServer;
@GetMapping(value = “/getYhmTomcatInfo”)
public String start() {
return yhmTomcatServer.run();
}
}
执行结果:
在application.properties 中配置:
yhm.tomcat.webRoot=testWebRoot
yhm.tomcat.port=9999
重启服务再次访问: