zoukankan      html  css  js  c++  java
  • SpringBoot自动装配

    需要了解如下问题

    自动装配解决了那些问题

    SpringBoot是spring的一个快速整合的开发工具包。我们使用SpringBoot很快创建一个项目。无需像Spring那样繁琐的配置。只需要引入不同的使用场景的starter就能完成自己功能的开发。
    例如如果要使用Web模块,那么就只需要引入web相关的starter就好了。
    IDEA使用Spring初始化器创建项目
    创建出来的springboot项目中pom.xml的dependences如下

       <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    ```xml
    ### 自动装配是如何完成的
    解读spring boot 的启动中的自动装配过程:
    使用的是redis来复原SpringBoot启动装配过程:
    ```java
    ConfigurationClassParser :
        protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
            if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
                return;
            }
            ConfigurationClass existingClass = this.configurationClasses.get(configClass);
            if (existingClass != null) {
                if (configClass.isImported()) {
                    if (existingClass.isImported()) {
                        existingClass.mergeImportedBy(configClass);
                    }
                    // Otherwise ignore new imported config class; existing non-imported class overrides it.
                    return;
                }
                else {
                    // Explicit bean definition found, probably replacing an import.
                    // Let's remove the old one and go with the new one.
                    this.configurationClasses.remove(configClass);
                    this.knownSuperclasses.values().removeIf(configClass::equals);
                }
            }
            // Recursively process the configuration class and its superclass hierarchy.
            //递归处理类上的注解,其中有有一个import的注解
            SourceClass sourceClass = asSourceClass(configClass, filter);
            do {
                sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
            }
            while (sourceClass != null);
            this.configurationClasses.put(configClass, configClass);
        }
    
    Application上面的注解:
    @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 {
    }
    

    其中@EnableAutoConfiguration注解用来启用自动配置:

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

    会Import一个自动配置导入选择器:AutoConfigurationImportSelector
    其中关键的代码:

            @Override
            public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
                Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
                        () -> String.format("Only %s implementations are supported, got %s",
                                AutoConfigurationImportSelector.class.getSimpleName(),
                                deferredImportSelector.getClass().getName()));
                AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
                        .getAutoConfigurationEntry(annotationMetadata); //将spring.factories里面的配置读出来
                this.autoConfigurationEntries.add(autoConfigurationEntry);
                for (String importClassName : autoConfigurationEntry.getConfigurations()) {
                    this.entries.putIfAbsent(importClassName, annotationMetadata);
                }
            }
            @Override
            public Iterable<Entry> selectImports() {
                if (this.autoConfigurationEntries.isEmpty()) {
                    return Collections.emptyList();
                }
                Set<String> allExclusions = this.autoConfigurationEntries.stream()
                        .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
                Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
                        .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
                        .collect(Collectors.toCollection(LinkedHashSet::new));
                processedConfigurations.removeAll(allExclusions);
                return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
                        .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
                        .collect(Collectors.toList());
            }
    

    另外并不是所有写在spring.factories里面的文件都会被装配进来,其中有spring强大的条件计算器来去做这件事情。

    如何写一个starter

    写代码。包括configuration和condition类
    写spring.factories
    外部引入这个starter

  • 相关阅读:
    Vtune 学习笔记 1 Finding Hotspots
    成都 宏碁 售后地址 官方
    Vtune 学习笔记 分析锁 Tutorial: Analyzing Locks and Waits
    (技术贴)铁道部12306网站瘫痪:网络购票技术之罪
    【转】移植之乱谈 深入理解Android 卷I作者谈
    FastReport集粹(一)
    FastReport集粹(二)
    在TDBGrid控件中为作修改过的记录进行标识!
    从此开始我的OGRE开发3D游戏之旅行。
    DBGrid 应用全书
  • 原文地址:https://www.cnblogs.com/lijunyzzZ/p/14311417.html
Copyright © 2011-2022 走看看