一:原理
1.
首先Spring Boot项目中都会如下启动类:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
其中,@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 {
所以,来说说@EnableAutoConfiguration的作用。
1 @Target(ElementType.TYPE) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 @Import(EnableConfigurationPropertiesImportSelector.class) 5 public @interface EnableConfigurationProperties {
2.作用
借助AutoConfigurationImportSelector
,@EnableAutoConfiguration
可以帮助SpringBoot应用将所有符合条件的@Configuration
配置都加载到当前SpringBoot创建并使用的IoC容器。
借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration
可以智能的自动配置功效才得以大功告成!
3.进一步说明如何加载
在AutoConfigurationImportSelector类中可以看到通过 SpringFactoriesLoader.loadFactoryNames()把 spring-boot-autoconfigure.jar/META-INF/spring.factories中每一个xxxAutoConfiguration文件都加载到容器中。
spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:
@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效
二:示例
1.结构
2.说明
在加载的时候,会通过一些注解进行匹配,然后都通过了,@EnableConfiguration才可以加载。
同时,可以不写@SpringBootApplication注解了。
3.说明项目
一共两个。
第一个是加载合适的bean
第二个是使用。
三:项目一
1.pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.jun</groupId> <artifactId>enableautoconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> <name>enableautoconfiguration</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>2.0.4.RELEASE</version> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
2.hello
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.jun</groupId> <artifactId>enableautoconfiguration</artifactId> <version>0.0.1-SNAPSHOT</version> <name>enableautoconfiguration</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>2.0.4.RELEASE</version> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
3.helloproperties
package com.jun.enableautoconfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "hello") //获取属性值 public class HelloProperties { private static final String MSG = "world"; private String msg = MSG ; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
4.helloautoconfiguration
1 package com.jun.enableautoconfiguration; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 5 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 6 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 7 import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.context.annotation.Configuration; 10 11 @Configuration //为带有@ConfigurationProperties注解的Bean提供有效的支持。 12 // 这个注解可以提供一种方便的方式来将带有@ConfigurationProperties注解的类注入为Spring容器的Bean。 13 @EnableConfigurationProperties(HelloProperties.class) //开启属性注入,通过@autowired注入 14 @ConditionalOnClass(Hello.class) //判断这个类是否在classpath中存在,如果存在,才会实例化一个Bean 15 @ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing = true) 16 public class HelloAutoConfiguration { 17 18 @Autowired 19 private HelloProperties helloProperties; 20 21 @Bean 22 @ConditionalOnMissingBean(Hello.class)//容器中如果没有Hello这个类,那么自动配置这个Hello 23 public Hello hello() { 24 Hello hello = new Hello(); 25 hello.setMsg(helloProperties.getMsg()); 26 return hello; 27 } 28 29 }
5.spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.jun.enableautoconfiguration.HelloAutoConfiguration
四:使用项目
1.application.properties
#可以不配置
hello.enabled=true
hello.msg=uuibiu
#以debug模式运行
debug=true
2.WenApplication
1 package com.jun.web; 2 3 import com.jun.enableautoconfiguration.Hello; 4 import org.slf4j.Logger; 5 import org.slf4j.LoggerFactory; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.boot.SpringApplication; 8 import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 9 import org.springframework.boot.autoconfigure.SpringBootApplication; 10 import org.springframework.context.ConfigurableApplicationContext; 11 import org.springframework.core.env.ConfigurableEnvironment; 12 import org.springframework.web.bind.annotation.RequestMapping; 13 import org.springframework.web.bind.annotation.RestController; 14 15 @SpringBootApplication 16 @EnableAutoConfiguration 17 @RestController 18 public class WebApplication { 19 private static final Logger logger = LoggerFactory.getLogger(WebApplication.class); 20 21 @Autowired 22 private Hello hello; 23 24 @RequestMapping("/") 25 public String index() { 26 return hello.sayHello(); 27 } 28 29 public static void main(String[] args) { 30 ConfigurableApplicationContext context = SpringApplication.run(WebApplication.class, args); 31 ConfigurableEnvironment environment = context.getEnvironment(); 32 logger.info("hello.msg:{}",environment.getProperty("hello.msg")); 33 34 } 35 36 }