0
点赞
收藏
分享

微信扫一扫

springboot使用Conditional细粒度控制Bean实例化


说明

在 springboot 中一个接口有多个实现,我们希望通过配置来控制​​运行时​​实例化哪个对象,springboot 中 @Conditional 注解可以帮助我们细粒度控制 bean 的实例化。

Bean对象

  • 两个 User Bean

@Data
@NoArgsConstructor
public class User1 {
private String name;
private int age;
}

@Data
@NoArgsConstructor
public class User2 {
private String name;
private int age;
}

方法一

  • 为每类对象创建一个 Conditional,如下为 User1和User2分别创建一个

public class MyConditional1 implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String v = context.getEnvironment().getProperty("user.label");
if (v.equals("user1")) return true;
return false;
}
}

public class MyConditional2 implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String v = context.getEnvironment().getProperty("user.label");
if (v.equals("user2")) return true;
return false;
}
}

  • springboot 实例化 bean

@Bean
@Conditional(MyConditional1.class)
public User init(){
System.out.println(111);
return new User();
}

@Bean
@Conditional(MyConditional2.class)
public User2 init2(){
System.out.println(222);
return new User2();
}

  • application.propeties

# 如果 label 匹配 bean 的label,该 bean 就会被实例化
user.label=user1

方法二

  • 新增注解给要实例化的对象打上标签

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(MyConditional.class)
public @interface MyConditionalAnnotation {
String label();
}

  • MyConditional.java

public class MyConditional extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyConditionalAnnotation.class.getName());
// 获取注解所传入的 label
Object value = annotationAttributes.get("label");
if (value == null) {
// return new ConditionOutcome(false, "ERROR");
return ConditionOutcome.noMatch("ERROR");
}
// user.label 的值是通过application.propeties传入
String v = context.getEnvironment().getProperty("user.label");
if (v.equals(value)){
// 如果匹配就实例化该 bean
return ConditionOutcome.match("OK");
}
return ConditionOutcome.noMatch("ERROR");
}
}

注意:代码中通过 ​​application.propeties​​ 传入配置优先级比较高,所以通过context可以获取到,如果通过别的配置文件可能无法获取则需要手动加载。

Properties properties = new Properties();
try {
properties.load(conditionContext.getResourceLoader().getResource("test.properties").getInputStream());
} catch (IOException ex) {
ex.printStackTrace();
}
String v = properties.getProperty("user.label");

  • springboot 创建bean

// 通过自定义注解设置 label
@MyConditionalAnnotation(label = "MyUserLabel1")
@Bean
public User1 init(){
System.out.println(111);
return new User1();
}

@MyConditionalAnnotation(label = "MyUserLabel2")
@Bean
public User2 init2(){
System.out.println(222);
return new User2();
}

  • application.propeties

# 如果 label 匹配 bean 的label,该 bean 就会被实例化
user.label=MyUserLabel2


举报

相关推荐

0 条评论