springboot自动配置的功能是由springboot启动类的注解@SpringBootApplication中的@EnableAutoConfiguration提供的。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
EnableAutoConfiguration里面的核心是EnableAutoConfigurationImportSelector,他的父类AutoConfigurationImportSelector通过调用SpringFactoriesLoader.loadFactoryNames方法来扫描具有META-INF/spring.factories文件的jar。
下面进行模拟
新建一个springboot项目,项目结构如下:
config目录下
@Configuration @EnableConfigurationProperties(HelloServiceProperties.class) @ConditionalOnClass(HelloService.class) @ConditionalOnProperty(prefix = "hello", value = "enabled", matchIfMissing = true) public class HelloServiceAutoConfiguration { @Autowired HelloServiceProperties helloServiceProperties; @Bean @ConditionalOnMissingBean(HelloService.class) public HelloService helloService() { HelloService helloService = new HelloService(); helloService.setMsg(helloServiceProperties.getMsg()); return helloService; } }
代码解释:根据HelloServiceProperties提供的参数,并通过ConditionalOnClass判断HelloService这个类在类路径中是否存在,且当容器中没有这个Bean的情况下自动配置这个Bean。
d@ConfigurationProperties(prefix = "hello") public class HelloServiceProperties { private static final String MSG = "world"; private String msg = MSG; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
service目录下:
public class HelloService { private String msg; public String sayHello() { return "Hello" + msg; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.vincent.config.HelloServiceAutoConfiguration
以上,一个带有自动配置的springboot项目已经完成,下面就来测试他。
在一个新的springboot项目中引入上面的项目
<dependency> <groupId>com.vincent</groupId> <artifactId>springboot-autoconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
新建一个测试controller
@RestController public class AutoconfigurationController { @Autowired HelloService helloService; @RequestMapping("/hello") public String hello() { return helloService.sayHello(); } }
将这个项目启动,访问http://localhost:8080/hello
结果如下:
我们修改下application.yml文件,在里面添加
hello: msg: aaa
重启项目,再次访问http://localhost:8080/hello
结果如下: