springboot 比 spring 多了什么?
现在springboot大行其道,很多面试官都会问,你觉得springboot对比spring有哪些不同?
springboot 是用于整合spring体系越来越复杂的框架,其底层本身就是spring。其目的是为了让我们更好的使用spring框架。
springboot 提供了非常多的start实现
- 能够快速创建基于Spring的应用程序;
- 能供直接使用java main 方法启动内置的Tomcat或者Jetty服务器运行...
- 提供约定的starter POM来简化Maven的配置,让Maven的配置变得更简单;
- 根据项目的Maven依赖配置,Spring Boot自动配置Spring、Spring ...
- 提供了程序的健康监控等功能;
用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加载元数据。
自定义一个自动装载功能
- 实现一个类
@Configuration public class DemoAutoconfiguration { @Bean public Demo demo() { return new Demo(); } }
- 在当前项目的资源文件中添加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。这大大提供了我们的研发效率,优化整体代码质量。
分析源码是学习架构的非常好的手段,带着设计模式、架构理念去看源码,收获良多。