1、组件装配
Spring Framework本身有一个IOC容器,该容器中会统一管理其中的bean对象,bean对象可以理解为组件。
- 组件:IOC容器中的核心API对象本身就是一个个的bean对象,即组件;
- 组件装配:将核心API配置到XML文件或注解配置类的行为称为组件装配。
Spring Framework本身只有一种组件装配方式,即手动装配,而Spring Boot基于原生的手动装配,通过模块装配+条件装配+SPI机制,可以完美实现组件的自动装配。
1.1、手动装配
指开发者在项目中通过编写XML配置文件、注解配置类、配合特定注解等方式,将所需的组件注册到IOC容器(AppLicationContext)中。
三种手动装配的方式:
(1)基于XML配置文件
<!--基于XML配置文件的手动配置-->
<bean id="AsyncTask"
class="com.demo.gov.gdc.commondatamodel.common.AsyncTask"/>
(2)基于注解配置类
@Configuration
public class DataModelConfig implements AsyncConfigurer {
public String getVersion() {
return "version";
}
/**
* 自定义线程池
*
* @return
*/
@Bean("lazyTraceExecutor")
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//此方法返回可用处理器的虚拟机的最大数量; 不小于1
int core = Runtime.getRuntime().availableProcessors();
executor.setCorePoolSize(core);//设置核心线程数
executor.setMaxPoolSize(core * 2 + 1);//设置最大线程数
executor.setKeepAliveSeconds(3);//除核心线程外的线程存活时间
executor.setQueueCapacity(40);//如果传入值大于0,底层队列使用的是LinkedBlockingQueue,否则默认使用SynchronousQueue
executor.setThreadNamePrefix("my-executor-");//线程名称前缀
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//设置拒绝策略
executor.initialize();
return executor;
}
}
(3)基于组件扫描
@Component
public class DmTypeDataService{
}
@ComponentScan(basePackages = { "com.demo.gov.gdc.commondatasource" })
@Configuration
public class DataSourceConfig {
public String getVersion() {
return "version";
}
}
从上述代码中可以提取出一个共性:手动装配都需要亲自编写配置信息,将组件注册到IOC容器中。
1.2、自动装配
Spring Boot的核心特征之一是组件的自动装配。自动装配的核心是,本应由开发者编写的配置,转为框架自动根据项目中整合的场景依赖,合理地做出判断并装配合适的Bean到IOC容器中。
Spring Boot利用模块装配+条件装配的机制,可以在开发者不进行任何干预的情况下注册默认所需要的组件,也可以基于开发者自定义注册的组件装配其他必要的组件,并合理地替换默认的组件注册(即覆盖默认配置)。
Spring Boot的自动装配可以实现配置禁用,通过在@SpringBootApplication或者@EnableAutoConfiguration注解上标注exclude/excludeName属性,可以禁用默认的自动配置类。
2、Spring Framework的模块装配
模块装配是自动装配的核心,它可以把一个模块所需的核心功能组件都装配到IOC容器中,并保证装配的方式尽可能的简单。Spring Framework中引入模块装配的表现形式是引入大量的@EnableXXX注解,可以实现快速激活和装配对应的模块。
比如:
- @EnableTransactionManagement:开启注解事务驱动
- @EnableWebMvc:激活SpringWebMvc整合Web开发
- @EnableAspectJAutoProxy:开启注解AOP编程
- @EnableScheduling:开启调度功能(定时任务)
…
2.1、模块
模块可以理解成一个个可以分解、组合、更换的独立单元。
模块的特性:
- 独立的;
- 功能高内聚;
- 可相互依赖;
- 目标明确;
模块装配的核心原则:自定义注解+@Import导入组件
2.2、Spring Framework的条件装配
为了解决在不同场景/条件下满足不同组件的装配,Spring Framework提供了两种条件装配的方式:基于Profile和基于Conditional。
2.2.1、基于Profile的装配
Profile提供了一种“基于环境的配置”:根据当前项目的不同运行时环境,可以动态的注册与当前运行环境匹配的组件。
2.2.2、基于Conditional的装配
@Conditional注解可以指定匹配条件,而被@Conditional注解标注的“组件类/配置类/组件工厂方法”必须满足@Conditional中指定的所有条件,才会被创建/解析。
2.4、SPI机制
服务提供方接口(Service Provider Interface,SPI)机制。
2.4.1、JDK原生的SPI
JDK原生的SPI使用范围有限,只能通过接口或抽象类来加载具体的实现,所以很多框架没有直接采用JDK的SPI,而是自定义了一套更强大的实现(Spring Framework、Double等框架都有自定义的SPI机制)。
代码示例:
1、定义接口+实现类
public interface Demo{}
2、声明SPI文件
3、测试获取
2.4.2、Spring Framework3.2的SPI
Spring Framework的SPI相较于JDK原生的SPI更加高级实用,因为它不仅限于接口或抽象类,而可以是任何一个类、接口或注解。
2.5、Spring Boot的装配机制
SpringBoot的自动装配实际就是模块装配+条件装配+SPI机制的组合使用。
2.5.1、@CompenentScan
@CompenentScan组件扫描
2.5.2、@SpringBootConfiguration
@SpringBootConfiguration注解并不是一个神秘的扩展,它本身仅组合了一个SpringFramework的@Configuration注解而已。
2.5.3、@EnableAutoConfiguration
@EnableAutoConfiguration注解承载了Spring Boot自动装配的灵魂。
2.6、WebMvc场景下的自动装配
一个实际且常见的场景:当项目整合SpringWebMvc后Spring Boot的自动装配做了什么?