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);
            }
        }
    }

}

基本就结束了

相关推荐
ikun12 分钟前
xwiki livedata筛选和分页
后端
郡杰18 分钟前
Java API
后端
林太白32 分钟前
Vite+React+ts项目搭建(十分钟搭建个最新版React19项目吧)
前端·后端·react.js
毕设源码-赖学姐34 分钟前
【开题答辩全过程】以 基于Springboot+微信小程序的网上家教预约系统的设计与实现-开题为例,包含答辩的问题和答案
spring boot·后端·微信小程序
LeeGe36 分钟前
MQ解决高并发下订单问题,实现流量削峰
后端
和平hepingfly43 分钟前
OpenAI 一统天下,联手谷歌和Cursor,开源AGENTS.md 标准,或将成为行业规范
后端
HyggeBest43 分钟前
Golang 并发原语 Sync Once
后端·go
煤球王子1 小时前
浅学内存布局(一)
后端
小蒜学长1 小时前
vue家教预约平台设计与实现(代码+数据库+LW)
java·数据库·vue.js·spring boot·后端
现在就干1 小时前
还在手忙脚乱创建线程?你的服务器是否扛得住生产环境的"狂风暴雨"?
后端