SpringBoot 自动装配

简介: SpringBoot 自动装配

SpringBoot自动装配是SpringBoot较springMVC最大的亮点。

SpringBootApplication注解

SpringBoot项目的入口类一般会标注@SpringBootApplication,其继承的注解有以下几个,也就是加入了注解就自动开始了自动装配,component扫描,同时入口类也是一个配置类Configuration。

@SpringBootApplication
包含如下注解
@SpringBootConfiguration   包含 @Configuration
@EnableAutoConfiguration
@ComponentScan

何时加载

从main入口SpringApplication.run进行跟踪,在refreshContext(context)进行加载ApplicationContext上下文,继续查找会找到处理@Configuration的类,再继续会找到 AutoConfigurationImportSelector来处理自动装配。

SpringApplication.run方法中
refreshContext(context);
⬇️
AbstractApplicationContext
invokeBeanFactoryPostProcessors(beanFactory);
⬇️
// 用来处理标记@Configuration的类
ConfigurationClassPostProcessor
processConfigBeanDefinitions(registry);
⬇️
//实现DeferredImportSelector用来处理 auto-configuration
AutoConfigurationImportSelector
process()
// 
AutoConfigurationEntry getAutoConfigurationEntry(...){
...
  // 获取配置
  List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
  configurations = removeDuplicates(configurations);
  // 排除项
  Set<String> exclusions = getExclusions(annotationMetadata, attributes);
  checkExcludedClasses(configurations, exclusions);
  configurations.removeAll(exclusions);
  // 过滤配置 AutoConfigurationImportFilter
  configurations = filter(configurations, autoConfigurationMetadata);
  // 广播事件
  fireAutoConfigurationImportEvents(configurations, exclusions);
...
}
⬇️
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;
    }
⬇️
// 真正指定EnableAutoConfiguration的地方
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }

从 META-INF/spring.factories加载 EnableAutoConfiguration指定的类

    /**
     * 从 META-INF/spring.factories 加载类名称
     * classloader ==> AppClassLoader
     
     * Load the fully qualified class names of factory implementations of the given type from      * "META-INF/spring.factories", using the given class loader.
     */
    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        String factoryTypeName = factoryType.getName();
        return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }

SpringFactoriesLoader类 获取加载工厂类

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
  ...
        try {
      // FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
            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 = PropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
          // key 作为factoryTypeName
                    String factoryTypeName = ((String) entry.getKey()).trim();
                    for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                        result.add(factoryTypeName, factoryImplementationName.trim());
                    }
                }
            }
        ...
    }

调试获取到13个配置项, V2.2.5版本

"org.springframework.boot.diagnostics.FailureAnalysisReporter" -> {LinkedList@4979}  size = 1
"org.springframework.boot.diagnostics.FailureAnalyzer" -> {LinkedList@4981}  size = 18
"org.springframework.boot.SpringBootExceptionReporter" -> {LinkedList@4983}  size = 1
"org.springframework.boot.SpringApplicationRunListener" -> {LinkedList@4985}  size = 1
"org.springframework.context.ApplicationListener" -> {LinkedList@4987}  size = 11
"org.springframework.boot.env.PropertySourceLoader" -> {LinkedList@4989}  size = 2
"org.springframework.context.ApplicationContextInitializer" -> {LinkedList@4991}  size = 7
"org.springframework.boot.env.EnvironmentPostProcessor" -> {LinkedList@4993}  size = 4
"org.springframework.boot.autoconfigure.AutoConfigurationImportListener" -> {LinkedList@4995}  size = 1
"org.springframework.boot.autoconfigure.AutoConfigurationImportFilter" -> {LinkedList@4997}  size = 3
"org.springframework.boot.autoconfigure.EnableAutoConfiguration" -> {LinkedList@4999}  size = 124
"org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider" -> {LinkedList@5001}  size = 5
"org.springframework.beans.BeanInfoFactory" -> {LinkedList@5003}  size = 1

AutoConfigurationImportFilter类型有3个,来进行配置过滤。

0 = "org.springframework.boot.autoconfigure.condition.OnBeanCondition"
1 = "org.springframework.boot.autoconfigure.condition.OnClassCondition"
2 = "org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition"

ConfigurationClassParser是加载配置的核心类

在doProcessConfigurationClass方法处理了如下注解及父类处理

@PropertySource
@ComponentScan
@Import
@Bean methods
  

总结:

自动装配的核心类有 ConfigurationClassPostProcessor、ConfigurationClassParser、AutoConfigurationImportSelector。

在ConfigurationClassPostProcessor配置类处理器,创建了ConfigurationClassParser对象对@Configuration注解的类进行处理,ConfigurationClassParser类持有DeferredImportSelector(即实现类AutoConfigurationImportSelector)对象实现对配置类的加载、过滤、排除最终获取到配置类。

SpringFactoriesLoader会加载META-INF/spring.factories下的所有类型并以key-value的形式数据进行缓存,自动配置获取以EnableAutoConfiguration为key的value即定义的配置类。

相关文章
|
9月前
|
XML Java Maven
Spring Boot自动装配原理
昨天,有位在广州工作4年的小伙伴,在面试中被问到SpringBoot自动装配原理,当时,自我感觉比较好,他要的是30K,但是都没有拿到Offer。今天,我给大家分享一下我的理解。
119 0
|
7月前
|
Java Spring 容器
【Spring Boot自动装配】
【Spring Boot自动装配】
|
8月前
|
NoSQL Java Redis
springboot自动装配
springboot自动装配
59 0
|
8天前
|
XML Java 数据库
【SpringBoot:详解Bean装配】
【SpringBoot:详解Bean装配】
10 3
|
19天前
|
Java
SpringBoot之@Conditional衍生条件装配详解
SpringBoot之@Conditional衍生条件装配详解
|
5月前
|
Java Maven Spring
【Spring Boot自动装配原理详解与常见面试题】—— 每天一点小知识(下)
【Spring Boot自动装配原理详解与常见面试题】—— 每天一点小知识(下)
121 0
|
5月前
|
Java Redis 开发者
【Spring Boot自动装配原理详解与常见面试题】—— 每天一点小知识(上)
【Spring Boot自动装配原理详解与常见面试题】—— 每天一点小知识
115 0
|
4月前
|
XML Java API
Springboot的自动装配解读
Spring Framework本身有一个IOC容器,该容器会统一管理其中的Bean对象,Bean对象可以理解为组件,要理解组件装配,首先要理解组件的概念。
|
4月前
|
存储 Java 开发工具
SpringBoot中Bean的条件装配
本文总结了在SpringBoot中常用的bean装配方法: * profile * conditional * ConditionalOn
42 1
|
4月前
|
XML Java 数据库
SpringBoot:详解Bean装配
SpringBoot:详解Bean装配
139 1