【springboot源码】springboot自动配置原理分析

17 篇文章 3 订阅
3 篇文章 0 订阅

注:本文阅读前提,对springboot基本使用有所了解,此外,其他一些源码解读,如果有需要,可以参考:

1.测试用例

  • 先搞个springboot项目来做测试用例
  • 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>source-code</artifactId>
        <groupId>com.source.code</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>spring-boot</artifactId>
    
    <!--版本控制-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.spring.platform</groupId>
                <artifactId>platform-bom</artifactId>
                <version>Cairo-SR7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <dependencies>
      <!--Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),-->
      <!-只需要在项目里面引入这些starter 相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--Spring Boot进行单元测试的模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <!--可运行jar包打包插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  • springboot启动主程序
/**
 * 启动器
 *@SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用 
 * @author wangjie
 * @version V1.0
 * @date 2020/2/9
 */
@SpringBootApplication
public class ApplicationStart {
    public static void main(String[] args) {
     // Spring应用启动起来 
        SpringApplication.run(ApplicationStart.class, args);
    }
}

2.springboot自动配置原理分析

  • 用springboot构建项目的优势不再赘述,有兴趣可以自行百度,今天我们对其自动配置功能做个探究
  • 入口就是springboot的主程序:
/**
 * 启动器
 *@SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用 
 * @author wangjie
 * @version V1.0
 * @date 2020/2/9
 */
@SpringBootApplication
public class ApplicationStart {
    public static void main(String[] args) {
     // Spring应用启动起来 
        SpringApplication.run(ApplicationStart.class, args);
    }
}
  • 注解@SpringBootApplication: 注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot 就通过运行这个类的main方法来启动SpringBoot应用:
  • 我们来看一下这个@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 {
  • @SpringBootConfiguration:Spring Boot的配置类注解, 标注在某个类上,表示这是一个Spring Boot的配置类;
  • @EnableAutoConfiguration:开启自动配置功能;今天聊的重点,springboot自动配置就是它在起作用
2.1 @EnableAutoConfiguration 开启自动配置功能
  • 我们打开@EnableAutoConfiguration:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
  • 我们挑重点来看:
  • @AutoConfigurationPackage自动配置包
  • @Import(AutoConfigurationImportSelector.class):@Import,Spring的底层注解,用来给容器中导入一个组件:AutoConfigurationImportSelector
  • 这两个重点注解我们一个一个来看:

2.1.1 @AutoConfigurationPackage:自动配置包注解

  • @AutoConfigurationPackage:自动配置包,简单说就是springboot在进行开启包扫描功能时,包扫描路径就是通过这个注解拿到的
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}
  • @AutoConfigurationPackage又是通过 @Import(AutoConfigurationPackages.Registrar.class)注解来完成的功能。
  • @Import(AutoConfigurationPackages.Registrar.class):Spring的底层注解@Import,给容器中导入一个组件:AutoConfigurationPackages.Registrar.class;
  • 我们来看一下这个类:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

       //给ioc容器注册一些bean定义信息
		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata,
				BeanDefinitionRegistry registry) {
			register(registry, new PackageImport(metadata).getPackageName());
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImport(metadata));
		}

	}
  • 我们来看看这个类中的registerBeanDefinitions()方法,它的作用是给ioc容器中注册一些bean定义信息,好在ioc容器创建时来创建这些bean。
  • 首先来看方法入参metadata,它是注解的源信息,我们可以通过Debug来看一下:
    在这里插入图片描述
  • 可以看到这个源信息里标注了这是@SpringBootApplication注解,是标注在ApplicationStart类上的。
  • 重点是在new PackageImport(metadata).getPackageName()这行代码。
  • 我们Debug算一下它的结果:
    在这里插入图片描述
  • 得到了我们主类的包路径:com.code.
  • 所以我们可以得到结论:AutoConfigurationPackages.Registrar.class这个组件的功能就是将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器。
  • 包扫描的路径拿到了,我们来看@EnableAutoConfiguration中下一个重要的注解@Import(AutoConfigurationImportSelector.class)

2.1.2 @Import(AutoConfigurationImportSelector.class)

  • @Import是Spring的底层注解,在这里用来给容器中导入一个组件:AutoConfigurationImportSelector
  • 我们来看一下这个AutoConfigurationImportSelector
public class AutoConfigurationImportSelector
		implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
		BeanFactoryAware, EnvironmentAware, Ordered {,,,}
  • AutoConfigurationImportSelector实现了DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,BeanFactoryAware, EnvironmentAware, Ordered等六个接口。
  • 其中类似BeanFactoryAware这样XXXAware这样的接口,功能都是类似的,就是在bean初始化的时候给bean中设置组件。
  • 简单说就是spring IOC容器会在实现了类似接口的bean实例化时调用一个invokeAwareMethods方法:
	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}
@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE - 1;// 2147483646感觉不怎么高
	}
  • 最后聊重点的DeferredImportSelector接口,AutoConfigurationImportSelector最核心的代码就是对此接口的实现,在看具体代码前,我们先来看看这个接口,看看它是用来做什么的:
public interface DeferredImportSelector extends ImportSelector {}
  • DeferredImportSelector 继承了ImportSelector ,我们打开ImportSelector :
/**
 * Interface to be implemented by types that determine which @{@link Configuration}
 * class(es) should be imported based on a given selection criteria, usually one or more
 * annotation attributes.
 *
 * <p>An {@link ImportSelector} may implement any of the following
 * {@link org.springframework.beans.factory.Aware Aware} interfaces, and their respective
 * methods will be called prior to {@link #selectImports}:
 * <ul>
 * <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
 * <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}</li>
 * <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}</li>
 * <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}</li>
 * </ul>
 *
 * <p>ImportSelectors are usually processed in the same way as regular {@code @Import}
 * annotations, however, it is also possible to defer selection of imports until all
 * {@code @Configuration} classes have been processed (see {@link DeferredImportSelector}
 * for details).
 *
 * @author Chris Beams
 * @since 3.1
 * @see DeferredImportSelector
 * @see Import
 * @see ImportBeanDefinitionRegistrar
 * @see Configuration
 */
public interface ImportSelector {

	/**
	 * Select and return the names of which class(es) should be imported based on
	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

}
  • 此接口上的英文说明大概意思是:

1,最基本的功能是向IOC容器里导入自定义bean

2,如果实现了此接口的bean也实现了EnvironmentAware ,BeanFactoryAware,BeanClassLoaderAware,ResourceLoaderAware这些接口,要先调用这些接口的实现

3,如果需要在所有 @Configuration配置都实例化时候再进行实例化,可以使用此接口的变种子类DeferredImportSelector

  • 而我们这里的这个bean ,就是实现了其变种子类DeferredImportSelector
  • 对于ImportSelector 接口的使用,我们可以写个Demo:
  • Demo:
/**
 * 自定义返回需要导入的组件
 * @see org.springframework.context.annotation.ImportSelector#selectImports(AnnotationMetadata)
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/6
 */
public class MyImportSelector implements ImportSelector {

    /**
     *
     * @param annotationMetadata 当前标注@Import的类所有注解信息 {@link org.springframework.core.type.AnnotationMetadata}
     * @return 导入到容器中组件全类名
     */
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.code.bean.Car"};
    }
}
  • 配置文件:
/**
 * 配置文件
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/5
 */
@Configuration
@Import({Home.class, MyImportSelector.class})
public class MyConfig3 {

}

  • 测试用例:
  @Test
    public void test01(){
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }
  • 运行结果:
myConfig3
com.code.bean.Home
com.code.bean.Car

Process finished with exit code 0

  • com.code.bean.Car是空的个实体类,这里就不贴了
  • 搞清楚了这个接口的作用,我们再回过头来看AutoConfigurationImportSelector对DeferredImportSelector的实现:
//这个方法就是来告诉springboot要导那些组件,方式就是通过String[]数组将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中,具体类似上方Demo
@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		//重点
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		//一顿操作,最后返回数组
		return StringUtils.toStringArray(configurations);
	}
  • 这个方法就是来告诉springboot要导那些组件,方式就是通过String[]数组将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中,具体类似上方Demo
  • 具体拿数组的方法就是List configurations = getCandidateConfigurations(annotationMetadata,
    attributes);这行代码,我们点进去:
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;
	}
  • 这个方法中重点是调用了SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
  • 其中入参getSpringFactoriesLoaderFactoryClass()
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
		return EnableAutoConfiguration.class;
	}
  • 拿到的是EnableAutoConfiguration.class这个自动加载工厂的名字
  • 另一个入参getBeanClassLoader是类加载器:
  • 我们对这个方法跟踪下去,会看到这样一个方法:
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
       //保存工厂类名字
		String factoryClassName = factoryClass.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
	}
	
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
		MultiValueMap<String, String> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		try {
		//用类加载器加载本地文件
			Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
			result = new LinkedMultiValueMap<>();
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
			   //	把类加载器加载出的资源转成Properties 文件
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				//遍历该配置文件key
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
				   //把properties解析到LinkedMultiValueMap中返回
					String factoryClassName = ((String) entry.getKey()).trim();
					for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
						result.add(factoryClassName, factoryName.trim());
					}
				}
			}
			cache.put(classLoader, result);
			return result;
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
	}
	
  • 这个方法重要的主要分三步:

  • 第一步:用类加载器加载本地资源

  • 加载的文件路径:

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
  • 第二步:把加载到的资源用key:value的形式保存到LinkedMultiValueMap中
  • 第三步:通过之前传进来的工厂类名字做key,从LinkedMultiValueMap拿到要返回的数组。
  • 最后,我把springboot META-INF/spring.factories目录下的配置文件中我们需要的部分贴一下,这里会被自动注册的组件就是它们:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
  • 它们会被解析成数组返回,再通过DeferredImportSelector接口注册进IOC容器中完成自动配置

【完】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值