新建工程
新建工程,com.example.myboot。
MybootProperties
@ConfigurationProperties(prefix = "myboot")
public class MybootProperties {
private String status;
private String msg;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
获取配置中前缀为myboot的配置,并将相应的属性进行填充。
MybootService
public class MybootService {
private MybootProperties mybootProperties;
public MybootService(MybootProperties mybootProperties) {
this.mybootProperties = mybootProperties;
}
public void mybootTest() {
System.out.println(mybootProperties.getStatus());
System.out.println(mybootProperties.getMsg());
}
}
MybootConfig
@Configuration
@ConditionalOnProperty(prefix = "myboot", value = "enable", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(MybootProperties.class)
public class MybootConfig {
@Bean
public MybootService mybootService(MybootProperties mybootProperties) {
return new MybootService(mybootProperties);
}
}
@ConditionalOnProperty
判断是否存在myboot.enable的属性,并且值为true,此时配置类生效,如果属性缺失了,也可以生效。
@EnableConfigurationProperties
使@ConfigurationProperties
标注的类注入到容器中,这里就是MybootProperties被注入到容器中。
@Bean生成一个MybootService对象注入到容器中,这里没加任何的@Conditional注解,后面会加自定义条件注解。
spring.factories
resources下新建META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.myboot.MybootConfig
使自动配置能扫描到MybootConfig。
打包
maven打包成myboot-starter-0.0.1-SNAPSHOT.jar
引入myboot-starter
配置pom
<dependency>
<groupId>com.example</groupId>
<artifactId>myboot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
验证
@Component
public class MyCommandLineRunner implements CommandLineRunner, ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void run(String... args) throws Exception {
System.out.println(">>> spring boot 启动完成 <<<");
MybootService mybootService = (MybootService) applicationContext.getBean("mybootService");
mybootService.mybootTest();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
这里通过启动加载器来验证。启动后,打印
>>> spring boot 启动完成 <<<
null
null
虽然没有配置任何myboot的属性,但是MybootConfig在缺省条件下也是认为匹配并加载的。
在application.properites
中配置myboot.enable=false
,再次启动,则会报错A component required a bean named 'mybootService' that could not be found.
设置myboot.enable=true
或者缺省
,然后设置myboot.status=OK
和myboot.msg=hello myboot stater
,再次启动
>>> spring boot 启动完成 <<<
OK
hello myboot stater
自定义条件注解@MyConditionAnnotation
@MyConditionAnnotation
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({MyValueCondition.class, MyStatusCondition.class})
public @interface MyConditionAnnotation {
String value() default "";
String status() default "";
}
MyValueCondition
public class MyValueCondition implements Condition, PriorityOrdered {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String value = (String) metadata.getAnnotationAttributes("com.example.myboot.MyConditionAnnotation").get("value");
if (StringUtils.isEmpty(context.getEnvironment().getProperty(value))) {
return false;
}
return true;
}
@Override
public int getOrder() {
return 1;
}
}
获取注解MyConditionAnnotation中的value属性,判断环境中value对应的属性是否有值,如果没有,认为该条件不匹配。实现了PriorityOrdered,定义order为1.
MyStatusCondition
public class MyStatusCondition implements Condition, PriorityOrdered {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String status = (String) metadata.getAnnotationAttributes("com.example.myboot.MyConditionAnnotation").get("status");
if (Objects.equals(context.getEnvironment().getProperty(status), "ok")) {
return true;
}
return false;
}
@Override
public int getOrder() {
return 2;
}
}
获取注解MyConditionAnnotation中的status属性,判断环境中status对应的属性值是否为ok,如果不是,认为该条件不匹配。实现了PriorityOrdered,定义order为2.
MybootConfig
@Configuration
@ConditionalOnProperty(prefix = "myboot", value = "enable", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(MybootProperties.class)
public class MybootConfig {
@Bean
@MyConditionAnnotation(value = "myboot.anno.value", status = "myboot.anno.status")
public MybootService mybootService(MybootProperties mybootProperties) {
return new MybootService(mybootProperties);
}
}
mybootService上面添加了@MyConditionAnnotation,这里就是判断环境属性myboot.anno.value是否有值并且myboot.anno.status为ok,全都满足了,才会将MybootService对象注入到容器中。
shouldSkip
中对Condition进行排序,然后依次判断各Condition是否满足,所以上面MyValueCondition(Order=1)会比MyStatusCondition(Order=2)先执行。多个Condition有一个不满足就会被跳过。