spring注解开发——按条件注册bean之@Conditional

按条件注册bean之@Conditional

需求:我们希望某些bean在特定环境下才注册到IOC容器,比如,根据当前操作系统的不同,选择性的注册一些bean到IOC容器中。

初识@Conditional注解,我们看看其注释:

Indicates that a component is only eligible for registration when all {@linkplain #value specified conditions} match.

意思是只有组件符合注册条件,组件才会被注册到IOC容器中。然后看看@Conditional定义:

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();
}

可以看到此注解需要一个Class类型的数组,数组元素为Condition类型,同时从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 the annotated component's registration
	 */
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

Condition是一个函数式接口,因此我们需要实现该接口,matches()里面就是我们要定义的匹配规则。

假如我们现在有两个bean,Windows bean和Linux bean,我们希望如果当前应用运行环境为Windows,就只注册Windows bean,如果为Linux,就只注册Linux bean。

两个bean的定义:

public class Windows {
    public Windows() {
        System.out.println("===> windows bean created...");
    }
}

public class Linux {
    public Linux() {
        System.out.println("===> linux bean created...");
    }
}

那么要选择性的注册这两个bean,我们需要为他们分别定义一个Condition,并在matches中写上我们的匹配规则:

public class WindowsCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String osName = environment.getProperty("os.name");
        System.out.println("windows condition ===> " + osName);

        if (osName.contains("Windows")) {
            return true;
        }
        return false;
    }
}

public class LinuxConditon implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        System.out.println("linux condition ===> " + property);

        if (property.contains("linux")) {
            return true;
        }
        return false;
    }
}

在配置文件中配置我们的bean,同时注解上注册bean的条件:

@Configuration
public class AnnotationBeanConfig {

    @Conditional({WindowsCondition.class})
    @Bean("Bill Gates")
    public Windows windows() {
        return new Windows();
    }

    @Conditional({LinuxConditon.class})
    @Bean("linus")
    public Linux linux() {
        return new Linux();
    }
}

测试类:

public class AnnotationBeanTest {

    @Test
    public void testBeanConditonal() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationBeanConfig.class);
        System.out.println("===> IOC container created..." );
    }
}

这里我们只创建IOC容器即可,因为在默认单例模式下,容器创建时就会把所有的单例bean注册到容器中。不清楚的可以看我上一篇博客:spring注解开发——bean的作用域和懒加载

结果:

windows condition ===> Windows 10
linux condition ===> Windows 10
===> windows bean created...
===> IOC container created...

可以看到,只有Windows bean注册到了容器中,在Linux环境下,大家可以自行去测试,看看是不是只有Linux bean被注册。

猜你喜欢

转载自blog.csdn.net/chenshufeng115/article/details/100052168