springboot——自动配置
自动配置是什么?什么是自动配置?举例来讲,当你通过@Autowired或@Resource注解,自动注入一个类实例之前,被注入进来的这个类实例需要被spring容器纳管,不然肯定会注入失败。往往我们会在xml通过`bean id="dfdf"` 或者在类定义上使用@Component、@Configuration等注解,来实现其被spring容器管理。而对于jar包中的类,则稍
自动配置是什么?
自动配置如何实现的?
使用@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<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> 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<String> 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;
}
loadFactoryNames会加载所有META-INF下有spring.factories文件的jar包,并根据spring.factories文件中的配置,去加载相应的类。
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
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文件看看:
利用自动配置,加载自定义jar包
看的差不多了,我们可以自己实现一个工具类,然后利用spring boot的自动配置。
自定义工具类
创建一个maven工程:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jzh</groupId>
<artifactId>envutils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
创建一个工具类:
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工程
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jzh</groupId>
<artifactId>AotuTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>com.jzh</groupId>
<artifactId>envutils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>
其中引用了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
更多推荐
所有评论(0)