使用@EnableAutoConfiguration注解,会启用自动配置
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration
该注解导入了EnableAutoConfigurationImportSelector,其selectImports方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
其通过getCandidateConfigurations 方法,获取配置文件列表:
protected List getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List 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;
}
loadFactoryNames会加载所有META-INF下有spring.factories文件的jar包,并根据spring.factories文件中的配置,去加载相应的类。
public static List loadFactoryNames(Class> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List result = new ArrayList();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
随便找一个spring.factories文件看看:
看的差不多了,我们可以自己实现一个工具类,然后利用spring boot的自动配置。
创建一个maven工程:
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.jzh
envutils
0.0.1-SNAPSHOT
创建一个工具类:
package envutils;
public class EnvUtils {
private String env = "test";
public String printEnv() {
System.out.println(env);
return env;
}
public String getEnv() {
return env;
}
public void setEnv(String env) {
this.env = env;
}
}
很简单,pringEnv方法,会返回env值,也就是“test"
接下来,就是在META-INF目录下,创建一个spring.factories文件,默认META-INF目录是没有的,我们手动创建一个:
其中写入:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
envutils.EnvUtils
同样的,我们再创建一个maven工程
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.jzh
AotuTest
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
1.5.0.RELEASE
com.jzh
envutils
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-autoconfigure
其中引用了spring的一些基础包,和我们上面创建的工具类
创建一个测试类:
package com.jzh.autotest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import envutils.EnvUtils;
@Controller
@EnableAutoConfiguration
public class AutoTest {
@Autowired
private EnvUtils envUtils;
@RequestMapping("/env")
@ResponseBody
public String env() {
String env = envUtils.printEnv();
return env;
}
public static void main(String args[]) {
SpringApplication.run(AutoTest.class,args);
}
}
运行,发现envUtils注入成功。
调用/env,返回test:
上面简单演示了自动配置。想一想,如果我们工程中,需要更改env值,应该怎么办?env.setEnv肯定有点丑陋了。能否读取文件中的配置呢?当然可以。
在工具上,添加@ConfigurationProperties(prefix="env")注解。
在测试类的配置文件中,添加:env.env=online(你想要设置给env的值)。
注意:当@ConfigurationProperties注解类中属性,添加@NotNull注解时,必须要在配置文件中设置,否则启动会报错。
参考:http://blog.sina.com.cn/s/blog_c90ce4e00103296u.html