自定義springboot starter和自定義條件註解

新建工程

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章