SpringBoot -- 自动化装配源码

自动化装配源码

      • [@EnableAutoConfiguration 注解,开启自动配置的核心注解](#@EnableAutoConfiguration 注解,开启自动配置的核心注解)
        • [@AutoConfigurationPackage 注解](#@AutoConfigurationPackage 注解)
      • [AutoConfigurationImportSelector 类](#AutoConfigurationImportSelector 类)
        • [getAutoConfigurationEntry 方法](#getAutoConfigurationEntry 方法)
        • [getCandidateConfigurations 方法](#getCandidateConfigurations 方法)
      • SpringFactoriesLoader

@EnableAutoConfiguration 注解,开启自动配置的核心注解

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

@EnableAutoConfiguration 包含了@AutoConfigurationPackage 注解和 @Import(AutoConfigurationImportSelector.class) 注解。

@AutoConfigurationPackage 注解

@AutoConfigurationPackage 通过 AutoConfigurationPackages.Registrar 将应用主类所在包及其子包下的所有组件扫描到Spring容器中。

重写这个方法就可以把包注册到spring 容器里面

有4个接口和一个注解都可以把对应类型放到容器里面,上文从源码来看是约定了一个接口,具体如何注册,看实现方式 AutoConfigurationPackages.register(registry, (new PackageImport(metadata)).getPackageName());



放到了定义map中

放到bean工厂,容器启动加载进去指的一说的是这个类,核心类 DefaultListableBeanFactory

从图中可以看到实现了 BeanFactory 接口和 ListableBeanFactory、ConfigurableListableBeanFactory、AutowireCapableBeanFactory 等多个接口。这个类是 Spring 容器的默认实现之一,是一个全功能的 Spring Bean 工厂,提供对 Bean 的完整管理,包括 Bean 的创建、定义、解析依赖、配置等功能

AutoConfigurationImportSelector 类

AutoConfigurationImportSelector 主要作用是收集和加载所有的自动配置类。

java 复制代码
public class AutoConfigurationImportSelector extends ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
}
getAutoConfigurationEntry 方法

getAutoConfigurationEntry 方法用于获取所有的自动配置类:

java 复制代码
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    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 new AutoConfigurationEntry(configurations, exclusions);
}
getCandidateConfigurations 方法

getCandidateConfigurations 方法从 spring.factories 文件中加载所有的候选配置类:

java 复制代码
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


SpringFactoriesLoader.loadFactoryNames 方法会读取 META-INF/spring.factories 文件中的配置,获取所有自动配置类的全限定名。

java 复制代码
public abstract class SpringFactoriesLoader {

    private static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();

    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 = (MultiValueMap)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            try {
                Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : 
                ClassLoader.getSystemResources("META-INF/spring.factories");


				// 下面先别管
                MultiValueMap<String, String> result = new LinkedMultiValueMap();


                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();
					

                    while(var6.hasNext()) {
                        Map.Entry<?, ?> entry = (Map.Entry)var6.next();
                        String factoryClassName = ((String)entry.getKey()).trim();
                        String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        int var10 = var9.length;

                        for(int var11 = 0; var11 < var10; ++var11) {
                            String factoryName = var9[var11];
                            result.add(factoryClassName, factoryName.trim());
                        }
                    }
                }

                cache.put(classLoader, result);
                return result;
            } catch (IOException var13) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
            }
        }
    }

}

基本就结束了

相关推荐
yyycqupt4 分钟前
多路转接之poll
服务器·c++·后端·网络协议
将登太行雪满山_1 小时前
自存 关于RestController请求传参数 前端和后端相关
java·前端·spring boot
吴冰_hogan1 小时前
nacos配置中心入门
java·spring boot·spring·springcloud
泰山小张只吃荷园1 小时前
通过SpringTask模拟打印机定时向数据库传入模拟数据
java·开发语言·后端·spring·mybatis
_可乐无糖1 小时前
iOS UI自动化 Appium的元素定位方式及比较
ios·appium·自动化
小技与小术2 小时前
go环境搭建
开发语言·后端·golang
伍肆伍柒2 小时前
SpringBoot 2.2.10 无法执行Test单元测试
spring boot·后端·单元测试
hummhumm2 小时前
第 14 章 -Go语言 错误处理
java·开发语言·前端·后端·python·sql·golang
HelpHelp同学2 小时前
如何利用知识中台实现客户服务自动化?
运维·自动化·知识库软件·内部知识库·搭建知识库
double丶flower2 小时前
Spring Boot 中使用 @Transactional 注解配置事务管理
数据库·spring boot·sql