• SpringBoot学习笔记(三)自动装配


    一.SpringBoot的自动装配

    1.@Import(AutoConfigurationImportSelector.class)

    1. public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
    2. ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered

    2.DeferredImprotSelector

    public interface DeferredImportSelector extends ImportSelector
    • DeferredImprotSelector是ImprotSelector的一种扩展
    • 在处理完所有的 @Configuration类型的Bean之后运行
    • 当导入@Conditional时,这种类型选择器特别有用
    • 实现还可以扩展Ordered接口,或使用@Order注解指示对其DeferredImportSelector优先级

    总结:

    • 执行时机:在@configuration注解中其他逻辑被处理完毕之后(包括对@ImprotResource,@Bean)再执行
    • DeferredImportSelector执行时机ImprotSelector更晚

    中其

    二.AutoConfigurationImportSelector的核心

    1. @override
    2. public String[] selectImports(AnnotationMetadata annotationMetadata){
    3. if(!isEmabled(annotationMetadata)){
    4. return NO_IMPORTS;
    5. }
    6. AutoconfigurationMetadata autoConfigurationMetadata=AutoconfigurationMetadataLoder.loadMetadata(this.beanClassLoader);
    7. // 加载自动配置类
    8. AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
    9. annotationMetadata);
    10. return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    11. }

    三.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata)

    1. protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata){
    2. if(!isEnabled(annotationMetadata)){
    3. return EMPTY_ENTRY;
    4. }
    5. AnnotationAttributes attributes=getAttributes(annotationMetadata);
    6. //核心-加载候选的自动配置类
    7. List configurations=getCandidateConfigurations(annotationMetadata, attribute);
    8. configurations=removeDuplicates(configurations);
    9. Set exclusions=getExclusions(annotationMetadata, attributes);
    10. checkExcludedClasses(configurations, exclusions);
    11. configurations.removeAll(exclusions);
    12. configurations = filter(configurations, autoConfigurationMetadata);
    13. fireAutoConfigurationImportEvents(configurations, exclusions);
    14. return new AutoConfigurationEntry(configurations, exclusions);
    15. }

    四.SpringBoot使用的工厂机制

     1.java的SPI

    • SPI全称Service Provider Interface
    • jdk内置服务提供发现机制---动态替换发现的机制

     2.SpringFramework的SpringFactoriesLoader

     loadFactoryNames方法:

    1. public static List loadFactoryNames(Class factoryClass,@Nullable ClassLoader classLoader){
    2. String factoryClassName = factoryClass.getName();
    3. return laodSpringFactories(classLoader).getOrDefault(factoryClassName,Collections.emptyList());
    4. }

    3.loadSpringFactories的实现,其中有缓存的写法值得学习

    1. public static final String FACTORIES_RESOURCE_LOCATION="META-INF/spring.factories";
    2. private static final Map> cache=new ConcurrentReferenceHashMap<>();
    3. private static Map> loadSpringFactories(@Nullable ClassLoader classLoader){
    4. Map> result=cache.get(classLoader);
    5. if(result!=null){
    6. return result;
    7. }
    8. try{
    9. //获取当前 classpath 下所有jar包中有的 spring.factories 文件,并将它们加载到内存中
    10. Enumeration urls=(classLoader != null ?
    11. classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
    12. ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
    13. //每一个文件,并用 Properties 方式加载文件,之后把这个文件中每一组键值对都加载出来,放入 MultiValueMap 中
    14. result = new LinkedMultiValueMap<>();
    15. while (urls.hasMoreElements()) {
    16. URL url = urls.nextElement();
    17. UrlResource resource = new UrlResource(url);
    18. Properties properties = PropertiesLoaderUtils.loadProperties(resource);
    19. for (Map.Entry entry : properties.entrySet()) {
    20. String factoryClassName = ((String) entry.getKey()).trim();
    21. for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
    22. result.add(factoryClassName, factoryName.trim());
    23. }
    24. }
    25. }
    26. cache.put(classLoader, result);
    27. return result;
    28. }catch (IOException ex){
    29. throw new IllegalArgumentException("Unable to load factories from location [" +
    30. FACTORIES_RESOURCE_LOCATION +"]",ex );
    31. }
    32. }

    五.总结

    • AutoconfigurationImprotSelector 配合SpringFactoriseLoader可加载“META-INF/spring.factories”中配置@EnableAutoconfiguration对应的自动配置类
    • deferredImportSelector的执行时机比ImprotSelector更晚
    • SpringFramework 实现了自己的SPI技术,相比较于Java原生的SPI更灵活。
  • 相关阅读:
    【a链接】点击a链接跳到另一个页面中指定的地方
    Springboot开发时,对前端的请求参数,后端用于接受的实体类有没有必要校验为null?
    BGP联盟实验
    【NLP】文本预处理的概念、处理方法、数学公式
    AntDB数据并行加载工具的实现
    CEF 实现放大缩小视图功能
    UE5的引擎初始化流程
    [附源码]Python计算机毕业设计Django医疗纠纷处理系统
    猿创征文 | Docker实战:Linux环境安装Tomcat安装步骤
    MFC Windows 程序设计[234]之重复文件搜索工具(附源码)
  • 原文地址:https://blog.csdn.net/weixin_42369687/article/details/126492962