@Conditional注解使用与自定义验证注解
作用:Spring4推出了@Conditional注解,方便程序根据当前环境或者容器情况来动态注入bean,按照一定的条件进行判断,满足条件给容器注册bean。
源码:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
/**
* All {@link Condition Conditions} that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();//实现Condition类,定义bean是否注册的条件
}
参数value源码:
@FunctionalInterface
public interface Condition {
/**
* Determine if the condition matches.确定条件是否匹配
* @param context the condition context
* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked
* @return {@code true} if the condition matches and the component can be registered,
* or {@code false} to veto the annotated component's registration
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
demo:自定义是否注册bean的规则
-
创建实体类
public class User { private String name; private Integer age; public User(String name, Integer age) { this.name = name; this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } ... }
-
创建自定义bean注册校验规则
当bean的名字为boy的时候注册,反之不注册
public class BoyCondition implements Condition { //校验是否为boy类型的bean @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { StandardMethodMetadata standardMethodMetadata = null; //向下转型,为了使用子类的方法获取方法名 if (metadata instanceof StandardMethodMetadata) { standardMethodMetadata = (StandardMethodMetadata) metadata; } //如果方法名不匹配,就去看@Bean注解是否定义了beanName if (!"boy".equals(standardMethodMetadata.getMethodName())) { MergedAnnotations annotations = metadata.getAnnotations(); MergedAnnotation<Bean> beanMergedAnnotation = annotations.get(Bean.class); Map<String, Object> map = beanMergedAnnotation.asMap(); String[] name = (String[]) map.get("name"); //使用stream流判断是否符合条件,好处:延迟加载,当数组为空的时候,不会执行方法体中的内容,直接返回false if (!Stream.of(name).anyMatch(s -> "boy".equals(s))) { return false; } } return true; } }
-
创建UserBeanConfig类
@Configuration public class UserBeanConfig { @Bean @Conditional(BoyCondition.class) public User boy(){ return new User("boy",22); } @Bean @Conditional(BoyCondition.class) public User girl(){ return new User("girl",22); } }
-
测试类
public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(UserBeanConfig.class); Map<String, User> beansOfType = annotationConfigApplicationContext.getBeansOfType(User.class); System.out.println(beansOfType); } 打印结果:{boy=User{name='boy', age=22}} 当bean的名字不为boy的时候,不会创建bean
-
注解源码中Class<? extends Condition>[] value()验证条件可以配置多个
定义新的验证条件
public class UserCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { return false; } }
-
修改UserBeanConfig类
@Configuration @Conditional({BoyCondition.class,UserCondition.class}) public class UserBeanConfig { @Bean(name = "boy") @Conditional({BoyCondition.class,UserCondition.class}) public User boy(){ return new User("boy",22); } }
-
经过多次测试运行结果:
@Conditional({BoyCondition.class,UserCondition.class}) 谁在前面先执行谁的验证(此时先执行BoyCondition) 当BoyCondition返回ture,UserCondition返回false,那么bean不加载 当BoyCondition返回true,UserCondition返回true,那么bean加载