美文网首页
SpringBoot原理

SpringBoot原理

作者: 小鱼_a563 | 来源:发表于2021-04-25 09:56 被阅读0次

    SpringBoot最大特点:自动装配

    pom.xml

    • spring-boot-dependencies: 核心依赖都在父工程中定义好了,通过spring-boot-starter-parent进去。
      我们中写或者引入springBoot依赖的时候,不需要写版本号,因为里面已经有了


      spring-boot-starter-parent

    启动器

     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-........</artifactId>
            </dependency>
    
    • 启动器:就是SpringBoot的启动场景,比如数据库连接,消息队列等等

    注解

    @SpringBootApplication//springboot启动注解,启动类下面所有的资源被导入,下面有很多子注解
    @SpringBootConfiguration//SpringBoot配置注解
    @ComponentScan//包扫描注解,扫描同级及其下面的包注入到应用中
    @EnableAutoConfiguration//启用自动配置注解---重要
    @AutoConfigurationPackage//自动配置包
    @Import({AutoConfigurationImportSelector.class})//导入AutoConfigurationImportSelector类(自动配置选择类)----重要
    

    AutoConfigurationImportSelector

      public String[] selectImports(AnnotationMetadata annotationMetadata) {
            if (!this.isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            } else {
                //获取自动配置实体类
                AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
                return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
            }
        }
     //获取自动配置实体类
    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
            if (!this.isEnabled(annotationMetadata)) {
                return EMPTY_ENTRY;
            } else {
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                //通过配置文件获取所有的start启动器,返回一个集合(getCandidateConfigurations)
                List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                configurations = this.removeDuplicates(configurations);
                Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                this.checkExcludedClasses(configurations, exclusions);
                configurations.removeAll(exclusions);
                configurations = this.getConfigurationClassFilter().filter(configurations);
                this.fireAutoConfigurationImportEvents(configurations, exclusions);
                return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
            }
        }
    //从字面意思就是获取获取候选配置
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
            //通过类名加载自动注入
            List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
            //如果为null,就返回提示,在META-INF / spring.factories中找不到自动配置类。 如果您使用的是自定义包装,请确保该文件正确无误。这就告诉我们 spring.factories非常重要:里面告诉了我们所有的可以自动配置的类。当然我们也可以从loadFactoryNames()方法中的loadSpringFactories()方法知道是从spring.factories匹配类名,然后加载出来的
            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;
        }
    
    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
            ClassLoader classLoaderToUse = classLoader;
            if (classLoader == null) {
                classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
            }
    
            String factoryTypeName = factoryType.getName();
            return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
        }
    
    private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
            Map<String, List<String>> result = (Map)cache.get(classLoader);
            if (result != null) {
                return result;
            } else {
                HashMap result = new HashMap();
                try {
                    //获取资源目录下面META-INF/spring.factories所有的url
                    Enumeration urls = classLoader.getResources("META-INF/spring.factories");
                    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()) {
                            Entry<?, ?> entry = (Entry)var6.next();
                            String factoryTypeName = ((String)entry.getKey()).trim();
                            String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                            String[] var10 = factoryImplementationNames;
                            int var11 = factoryImplementationNames.length;
                            for(int var12 = 0; var12 < var11; ++var12) {
                                String factoryImplementationName = var10[var12];
                                ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
                                    return new ArrayList();
                                })).add(factoryImplementationName.trim());
                            }
                        }
                    }
    
                    result.replaceAll((factoryType, implementations) -> {
                        return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
                    });
                    //放入到缓存中
                    cache.put(classLoader, result);
                    return result;
                } catch (IOException var14) {
                    throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
                }
            }
        }
    

    结论: springboot所有自动配置都是在启动的时候加载: spring.factories所有的自动配置类都在这里
    面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!

    1. springboot在启动的时候,从类路径下/META-INF/ spring . factories获取指定的值;
      2.将这些自动配置的类导入容器,自动配置就会生效,帮我进行自动配置!
      3.以前我们需要自动配置的东西,现在springboot帮我们做了!
      4.整合javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.2.0.RELEASE.jar这个包下
      5.它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
      6.容器中也会存在非常多的xxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要
      的所有组件;并自动配置,@Configuration
      7.有了自动配置类,免去了我们手动编写配置文件的工作

    SpringApplication.run

    1.推断应用的类型是普通的项目还是Web项目
    2.查找并加载所有可用初始化器,设置到initializers属性中
    3.找出所有的应用程序监听器,设置到listeners属性中
    4.推断并设置main方法的定义类,找到运行的主类

    相关文章

      网友评论

          本文标题:SpringBoot原理

          本文链接:https://www.haomeiwen.com/subject/ltuggktx.html