自定义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有一个不满足就会被跳过。

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