欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【springboot】之自动配置原理

程序员文章站 2023-12-06 13:56:52
使用springboot开发web应用是很方便,只需要引入相对应的GAV就可以使用对应的功能,springboot默认会帮我们配置好一些常用配置。那么springboot是怎么做到的呢?这篇文章将一步步跟踪源码,查看springboot到底是如何帮我们做自动化配置。 springboot核心注解 可 ......

使用springboot开发web应用是很方便,只需要引入相对应的gav就可以使用对应的功能,springboot默认会帮我们配置好一些常用配置。那么springboot是怎么做到的呢?这篇文章将一步步跟踪源码,查看springboot到底是如何帮我们做自动化配置。

springboot核心注解

@springbootapplication

 

 【springboot】之自动配置原理

 

【springboot】之自动配置原理

 

可以看到使用@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)

【springboot】之自动配置原理

 

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】之自动配置原理

 

 springboot将会加载(org.springframework.boot.autoconfigure.enableautoconfiguration)所对应的所有自动配置到spring ioc容器中

 

自动配置如何生效

以(org.springframework.boot.autoconfigure.web.multipartautoconfiguration)为例。

【springboot】之自动配置原理

 

 

我们看到当前自动配置类核心在这几个注解。

@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即可。