【springboot】之自动配置原理
使用springboot开发web应用是很方便,只需要引入相对应的gav就可以使用对应的功能,springboot默认会帮我们配置好一些常用配置。那么springboot是怎么做到的呢?这篇文章将一步步跟踪源码,查看springboot到底是如何帮我们做自动化配置。
springboot核心注解
@springbootapplication
可以看到使用@import导入一个开启自动配置的选择器
@import的作用,官方源码
* @author chris beams * @since 3.0 * @see configuration * @see importselector * @see importresource */ @target(elementtype.type) @retention(retentionpolicy.runtime) @documented public @interface import { /** * the @{@link configuration}, {@link importselector} and/or * {@link importbeandefinitionregistrar} classes to import. */ class<?>[] value(); }
导入@configuration注解的配置类
导入importselector的实现类
导入importbeandefinitionregistrar的实现类
接着看导入的这个选择器(@enableautoconfigurationimportselector.class)
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; }
这里方法调用了两个核心方法
1、 getspringfactoriesloaderfactoryclass(),我们发现返回的是enableautoconfiguration.class
2、loadfactorynames这个方法
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 propertyvalue = properties.getproperty(factoryclassname); for (string factoryname : stringutils.commadelimitedlisttostringarray(propertyvalue)) { result.add(factoryname.trim()); } } return result; } catch (ioexception ex) { throw new illegalargumentexception("unable to load factories from location [" + factories_resource_location + "]", ex); } }
先获取factoryclass(enableautoconfiguration)的classname(org.springframework.boot.autoconfigure.enableautoconfiguration),
将这个classname当做property的key值,来获取value。springboot默认会全局扫描factories_resource_location
public static final string factories_resource_location = "meta-inf/spring.factories";
springboot将会加载(org.springframework.boot.autoconfigure.enableautoconfiguration)所对应的所有自动配置到spring ioc容器中
自动配置如何生效
以(org.springframework.boot.autoconfigure.web.multipartautoconfiguration)为例。
我们看到当前自动配置类核心在这几个注解。
@configuration @conditionalonclass({ servlet.class, standardservletmultipartresolver.class, multipartconfigelement.class }) @conditionalonproperty(prefix = "spring.http.multipart", name = "enabled", matchifmissing = true) @enableconfigurationproperties(multipartproperties.class)
@configuration spring注解配置类
@conditionalonclass 意思是存在某个类,当前配置生效
@conditionalonproperty 意思是否存在开启的spring.http.multipart 的配置,这里默认开启,对应的是springboot主配置文件(application)文件中配置项目
@enableconfigurationproperties 意思是将multipartproperties类加入spring容器,等价于在multipartproperties类上加 @component注解
我们去看一下multipartproperties类是干什么了?
@configurationproperties(prefix = "spring.http.multipart", ignoreunknownfields = false) public class multipartproperties {
@configurationproperties 读取springboot主配置文件(application.prperties)的配置
所以最后发现只要满足@conditionalxxxx条件 ,当前自动配置类即可生效。
以上就是springboot的自动配置原理,如果我们想知道引入的某个gav可以配置哪些属性,主需要找到对应的xxxautoconfiguration 查看对应的
@enableconfigurationproperties(xxxx.class)引入的class即可。