@Condition是Spring4新增的注解,作用是在满足条件时将bean注入到Spring容器,在Spring Boot中大量用到了@Condition注解,例如@ConditionOnBean等为Spring Boot自动化配置的核心。源码:
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditional { /** * All {@link Condition}s that must {@linkplain Condition#matches match} * in order for the component to be registered. */ Class<? extends Condition>[] value(); }
注解的value是一个Condition接口的实现,Condition接口源码:
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 registration. */ boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
我们做一个简单的实例,根据设置的profile不同,在Spring容器中注册的bean也不同,首先定义一个Service接口:
public interface ProfileService { void show(); }
再定义两个实现类:
public class ProfileDevService implements ProfileService { @Override public void show() { System.out.println("this is dev"); } }
public class ProfilePrdService implements ProfileService { @Override public void show() { System.out.println("this is prd"); } }
这两个类只能在Spring窗口中注册一个,方法就是判断profile,两个判断类:
public class OnDevProfile implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return context.getEnvironment().getActiveProfiles()[0].equals("dev"); } }
public class OnPrdProfile implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return context.getEnvironment().getActiveProfiles()[0].equals("prd"); } }
这两个类都实现了Condition接口,在注解@Condition需要用到这两个类:
@Configuration public class ConditionConfiguration { @Bean @Conditional(OnDevProfile.class) public ProfileService devProfileService() { return new ProfileDevService(); } @Bean @Conditional(OnPrdProfile.class) public ProfileService prdProfileService() { return new ProfilePrdService(); } }
在注入bean时加上了@Condition注解,所以能否注册成功,取决于@Condition注解的value类的matchs方法返回值。
启动一个容器:
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("prd"); context.register(ConditionConfiguration.class); context.refresh(); ProfileService profileService = context.getBean(ProfileService.class); profileService.show(); context.close(); }
这里设置active profiles为"prd",因此控制台打印的是this is prd,将active profiles改为"dev"打印的是this is dev