SpringBoot 扩展机制 ——Spring.factories文件 如何将外部项目加入Spring容器
▶ 简介
简单说用于模块之间解耦,外部项目下各种配置、类加入到Spring容器中进行管理,类似JAVA中SPI机制。机制自行百度。
▶ 方式
将外部类引入IOC容器两种方式
1.@import
2.加入Spring.factories文件 — 主讲这个
▶ Spring.factories文件
1.在resource目录下 meta-INF/ Spring.factories 文件
2.格式:自定义需要扫描到类(接口),多个用 ”,“ 隔开
3.SpringFactoriesLoader类会去扫描加载文件下定义类,加入容器
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.mostsnails.common.base.utils.config.WebLogAutoConfiguration,
com.mostsnails.common.base.utils.config.RedisAutoConfiguration,
com.mostsnails.common.base.utils.test.TestClass
注意这里使用EnableAutoConfiguration ,SpringBoot启动类@SpringBootApplication注解包下有@EnableAutoConfiguration和@Component 具体作用开启自动装备,将满足条件@Configuration配置加入到SpringBoot中。
Spring.factories也可以包含其他类型
# Initializers
org.springframework.context.ApplicationContextInitializer=
org.springframework.boot.autoconfigure.SharedmetadataReaderFactoryContextInitializer,
org.springframework.boot.autoconfigure.logging.ConditionevaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=
org.springframework.boot.autoconfigure.BackgroundPreinitializer
....
可以去看项目下spring-boot-***-start jar包
外部项目下Redis配置类
@Configurable
public class RedisAutoConfiguration {
private static org.slf4j.Logger log = LoggerFactory.getLogger(RedisAutoConfiguration.class);
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
// 创建RedisTemplate对象
RedisTemplate template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
// 定义Jackson2JsonRedisSerializer序列化对象
Jackson2JsonRedisSerializer
▶ 延伸扩展 — 选择性加载@Conditional 和 @ConditionalOn***
在一些自动装配配置类中 出现过 @ConditionalOn***,@EnableAutoConfiguration会在满足条件情况下加入IOC容器
public class WebLogAutoConfiguration {
private static org.slf4j.Logger log = LoggerFactory.getLogger(WebLogAutoConfiguration.class);
public WebLogAutoConfiguration() {
log.info("Web日志记录配置类.....Start");
}
@Bean
@ConditionalOnWebApplication//当项目是一个Web项目时进行实例化
@ConditionalOnMissingBean(WebLogAspect.class)//当容器里没有指定Bean的条件下进行实例化。
public WebLogAspect webLogAspect() {
log.info("注入webLogAspect类.....");
return new WebLogAspect();
}
}
▶ 更多@Conditional 注解
@ConditionalOnBean: 仅仅在当前上下文中存在某个对象时,才会实例化一个Bean。
@ConditionalOnClass: 某个class位于类路径上,才会实例化一个Bean。
@ConditionalOnexpression:当表达式为true的时候,才会实例化一个Bean。
@ConditionalOnMissingBean:仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean。
@ConditionalOnMissingClass:某个class类路径上不存在的时候,才会实例化一个Bean。
@ConditionalOnNotWebApplication:不是web应用,才会实例化一个Bean。
@ConditionalOnBean: 当容器中有指定Bean的条件下进行实例化。
@ConditionalOnMissingBean:当容器里没有指定Bean的条件下进行实例化。
@ConditionalOnClass: 当classpath类路径下有指定类的条件下进行实例化。
@ConditionalOnMissingClass:当类路径下没有指定类的条件下进行实例化。
@ConditionalOnWebApplication:当项目是一个Web项目时进行实例化。
@ConditionalOnNotWebApplication:当项目不是一个Web项目时进行实例化。
@ConditionalOnProperty: 当指定的属性有指定的值时进行实例化。
@ConditionalOnexpression: 基于SpEL表达式的条件判断。
@ConditionalOnJava: 当JVM版本为指定的版本范围时触发实例化。
@ConditionalOnResource: 当类路径下有指定的资源时触发实例化。
@ConditionalOnJndi: 在JNDI存在的条件下触发实例化。
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化。
▶ 如何使用IOC容器对象
1.@Autowired 2.ApplicationContext
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebDemoApplication.class)
public class JunitTest {
// @Autowired
// private TestClass testClass;
@Test
public void customYAMLTest(){
TestClass bean = BeanFactoryUtil.getBean(TestClass.class);
System.out.println(JSON.toJSonString(bean));
}
}
BeanFactoryUtil
public class BeanFactoryUtil {
private static ApplicationContext context;
public static void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (context == null){
context = applicationContext;
}
}
// 获取applicationContext
private static ApplicationContext getApplicationContext() {
return context;
}
// 通过name获取Bean
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
// 通过class获取Bean
public static T getBean(Class clazz) {
return getApplicationContext().getBean(clazz);
}
// 通过name,以及Clazz返回指定的Bean
public static T getBean(String name, Class clazz) {
return getApplicationContext().getBean(name, clazz);
}
}