简介
SpringBoot
为我们提供了是非便利的自动装配功能,让我们能轻松的在团队合作中发布自己或者小团队的组件,其他团队能很便捷的引用,下面我们来看看工作中常用的一些处理自动配置的技巧。
自动配置
我们只需要在项目resources/META-INF/spring.factories
文件中增加org.springframework.boot.autoconfigure.EnableAutoConfiguration
节点,并配置需要自动配置的类,SpringBoot
就可以为我们完成该类的加载,如果有多个类需要自动配置用逗号隔开。
举例:
// resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.demo.DemoAutoConfigure
具体原理《SpringBoot自动配置及自定义Starter》
使用
规范
自动配置的类不能被扫描,同时也不能在自动配置的类中扫描其他类,如果需要引入其他类可以使用@Import
注解,举例:
@Import({
DemoService.class
})
public class DemoAutoConfigure {
}
这是一个最简单的自动配置类,我们也不需要在类上添加@Configuration
注解,SpringBoot
会自动将该类加载成Bean
,该自动配置只做了一件事就是将DemoService
加载到ApplicationContext
中,我们在后续使用中只需要直接注入到使用的地方即可。
public Class TestService{
@Autowird
private DemoService demoService;
}
顺序控制
@AutoConfigureAfter
和@AutoConfigureBefore
,如果需要控制自动配置的加载顺序,我们可以使用这两个注解,顾名思义这两个注解是控制后加载和前加载的,举例:
@AutoConfigureBefore({DataJdbcRuntimeAutoConfigure.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class DemoAutoConfigure {
@Bean
public DemoService demoService(DataSource dataSource){
return new DemoService(dataSource);
}
}
这个例子中我们删除了@Import
注解,采用@Bean
注解将DemoService
声明为一个bean
对象并加载到spring
容器中,我们通过构造函数new
了一个DemoService
对象,该对象需要一个DataSource
作为参数,我们可以方法参数的形式直接将DataSource
参数注入到demoService()
方法中并传递给new DemoService(dataSource)
所以我们需要保证在DemoAutoConfigure
加载时DataSource
对象已经加载到了spring
容器中,这时就可以采用@AutoConfigureAfter({DataSourceAutoConfiguration.class})
来保证自动配置的加载顺序。
条件控制
@ConditionalOnClass和@ConditionalOnMissingClass
这两个注解控制自动配置类需要在有某个类或者没有某个类时才加载,比如:
@ConditionalOnClass(DemoService.class)
public class DemoAutoConfigure {
@Bean
public DemoService demoService(){
return new DemoService();
}
}
DemoAutoConfigure
只有在DemoService
存在的时候才会加载,这在我们增强一些组件时是很有用的,只有存在时才增强。
@ConditionalOnBean和@ConditionalOnMissingBean
这两个注解控制自动配置类需要在ApplicationContext
存在这个类型的bean
对象才会加载,比如:
public class DemoAutoConfigure {
@Bean
@ConditionalOnMissingBean
public DemoService demoService(){
return new DemoService();
}
}
我们在demoService()
方法上标记了@Bean
和@ConditionalOnMissingBean
两个注解,这样在ApplicationContext
中不存在DemoService
类型的bean
对象时则会new
一个DemoService
并加载到ApplicationContext
中;利用这个特性我们可以给自己的组件定义默认的行为,同时组件使用者可以定义自己的DemoService
并加载到ApplicationContext
中以此来覆盖组件的默认行为。
@ConditionalOnProperty
@ConditionalOnProperty(value = "enabled", prefix = "demo", havingValue = "true", matchIfMissing = false)
public class DemoAutoConfigure {
@Bean
@ConditionalOnMissingBean
public DemoService demoService(){
return new DemoService();
}
}
该注解可以让我们用配置文件或者启动参数控制自动配置类是否加载,上面的例子表示,在配置参数中存在demo.enabled=true
时DemoAutoConfigure
才会加载,注意这个的配置参数不仅仅是配置文件中的参数,还包括环境变量、jvm参数、SpringApplicationJson参数等。我们平常用的框架经常会采用这种方式控制,比如:
spring:
application:
name: demo
cloud:
nacos:
discovery:
enabled: false //关闭nacos注册
测试
测试自动配置我们需要用到ApplicationContextRunner
class DemoAutoConfigureTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test
void demoServiceTest() {
this.contextRunner
.withPropertyValues("demo.enabled=true") //指定参数
.withConfiguration(AutoConfigurations.of(DemoAutoConfigure.class)) //指定配置类
.run((context) -> {
assertThat(context).hasSingleBean(DemoService.class);
assertThat(context).getBean("demoService").isSameAs(context.getBean(DemoService.class));
});
}
}
上面的例子中我们用withPropertyValues
指定了参数,withConfiguration
指定了配置类,AssertJ
进行了类型判断
自定义Starter
利用springboot自动配置定义自己的Starter可以参考《SpringBoot自动配置及自定义Starter》
至此本教程就结束了,希望大家收获满满
有问题欢迎留言