新建工程
新建工程,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有一個不滿足就會被跳過。