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

  • 相关阅读:
    C#开发微信门户及应用(18)-微信企业号的通讯录管理开发之成员管理
    C#开发微信门户及应用(17)-微信企业号的通讯录管理开发之部门管理
    C#开发微信门户及应用(16)-微信企业号的配置和使用
    C#开发微信门户及应用(15)-微信菜单增加扫一扫、发图片、发地理位置功能
    会员管理系统的设计和开发(3)--主界面的设计思路分享
    会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载
    Winform开发中常见界面的DevExpress处理操作
    在WCF数据访问中使用缓存提高Winform字段中文显示速度
    双指针算法模板和一些题目
    尾递归 递归函数中,递归调用是整个函数体中最后的语句,且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归,空间复杂度是O(1)
  • 原文地址:https://www.cnblogs.com/lijunyzzZ/p/14311417.html
Copyright © 2011-2022 走看看