美文网首页springboot
用好springboot,离不开自动装载机制

用好springboot,离不开自动装载机制

作者: 求索 | 来源:发表于2020-03-03 13:08 被阅读0次

springboot 比 spring 多了什么?

现在springboot大行其道,很多面试官都会问,你觉得springboot对比spring有哪些不同?

springboot 是用于整合spring体系越来越复杂的框架,其底层本身就是spring。其目的是为了让我们更好的使用spring框架。

springboot 提供了非常多的start实现

  1. 能够快速创建基于Spring的应用程序;
  2. 能供直接使用java main 方法启动内置的Tomcat或者Jetty服务器运行...
  3. 提供约定的starter POM来简化Maven的配置,让Maven的配置变得更简单;
  4. 根据项目的Maven依赖配置,Spring Boot自动配置Spring、Spring ...
  5. 提供了程序的健康监控等功能;

用springboot其目的是简化开发,提供开发效率。在框架搭建好,明确项目技术体系之后,日常开发我们就是在用spring,和直接基于spring的开发没有太多的区别。

但是有些场景,比如redis在开发环境禁用,发布到线上希望启用;开发环境使用swagger,生产环境希望屏蔽;低层框架封装特定的Bean组件,在特殊子系统中希望覆盖该组件。解决诸如此类的问题,是springboot在日常工作中最常见的需求。自动装载机制就是用于解决这些问题的。

自动装载机制原理介绍

@EnableAutoConfiguration 将自动装载机制导入spring bean加载体系。

@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

注解 @Import 的代码注释

Provides functionality equivalent to the {@code <import/>} element in Spring XML.

该注解提供与Spring XML中的{@code<import/>}元素等效的功能。在这里我们导入了 AutoConfigurationImportSelector类。

public class AutoConfigurationImportSelector
        implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
        BeanFactoryAware, EnvironmentAware, Ordered {
            //...
        }

通过类接口我们可以看到他实现了DeferredImportSelector接口,该接口包含selectImports方法。selectImports方法是用于扫描bean加载的元数据信息的。

    @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 方法调用了fireAutoConfigurationImportEvents方法。fireAutoConfigurationImportEvents又调用了。

    protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class,
                this.beanClassLoader);
    }

SpringFactoriesLoader.loadFactories通过加载资源文件 META-INF/spring.factories加载元数据。

自定义一个自动装载功能

  1. 实现一个类
    @Configuration 
    public class DemoAutoconfiguration {
        
        @Bean
        public Demo demo() {
            return new Demo();
        }
    }
    
  2. 在当前项目的资源文件中添加META-INF/spring.factories文件,并向其中添加刚才实现的类
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
        cn.xxx.demo.autoconfigure.DemoAutoconfiguration,\
    

满足上面两个条件,DemoAutoconfiguration里面定义的bean,就不需要在扫包就能直接使用了。当然DemoAutoconfiguration所在的jar,必须在你工程里面已经导入了。

上面仅仅是一个简单的实现,springboot提供了很多实现自动装载的注解

  • ConditionalOnClass
  • ConditionalOnProperty
  • ConditionalOnMissingBean
  • ConditionalOnMissingClass

如:

@Configuration
@EnableConfigurationProperties({DemoProperties.class})
@ConditionalOnClass({DemoJarExists.class})
@ConditionalOnProperty(name = "demo.enabled", havingValue = "true")
@Slf4j
public class DemoAutoconfiguration {

}

这个例子告诉bean加载时先判断DemoJarExists 类是否存在,如果不存在就跳过;同时要求配置项 demo.enabled =true 才能有效。

设计理念

自动装载机制通过META-INF/spring.factories 和 结果注解将可变性隔离,底层抽象出一套不可变的概念。任意的功能你都可以在自己的框架中重新覆盖实现,而且覆盖实现的成本仅仅是 实现一个Autoconfiguration。这大大提供了我们的研发效率,优化整体代码质量。

分析源码是学习架构的非常好的手段,带着设计模式、架构理念去看源码,收获良多。

相关文章

网友评论

    本文标题:用好springboot,离不开自动装载机制

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