7、组件注册-@Conditional-按照条件注册bean
- @Conditional 按照一定的条件进行判断,满足条件给容器注入bean
- 按照条件进行动态装配。
- Spring 4 开始提供的一个注解,Spring Boot底层大量运用此注解。
@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();
}
7.1 编写自定义的条件判断Condition
- 需求:根据当前的os.name判断,如果是Linux则注入linus,如果是Windos则注入bill
- MainConfig.java类下 新添加 linus 和bill两个bean。
/**
* 如果是windows 注册bill
*
* @return
*/
@Conditional({WindowsConditional.class})
@Bean("bill")
public Pension pension01() {
return new Pension("bill", 23);
}
/**
* linux
*
* @return
*/
@Bean("linus")
@Conditional({LinuxConditional.class})
public Pension pension02() {
return new Pension("linus", 48);
}
7.2 实现自定义的LinuxConditional 和 WindowsConditional
- 需要实现 org.springframework.context.annotation.Condition 接口,重写matches方法。
package com.hw.springannotation.conditional;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @Description TODO
* @Author hw
* @Date 2018/11/28 15:02
* @Version 1.0
*/
public class LinuxConditional implements Condition {
/**
* Determine if the condition matches.
*
* @param context 判断条件使用的上下文环境
* @param metadata 当前标注了该注解的注释信息
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO: 2018/11/28 判断是否是linux系统
// 1 能获取到ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 2 获取类加载器
ClassLoader classLoader = context.getClassLoader();
// 3 获取当前环境信息
Environment environment = context.getEnvironment();
// 4 获取bean定义的注册类
BeanDefinitionRegistry beanDefinitionRegistry = context.getRegistry();
// 判断容器中是否包含某个bean
boolean de = beanDefinitionRegistry.containsBeanDefinition("pension");
String property = environment.getProperty("os.name");
if (property.contains("Linux")) {
return true;
}
return false;
}
}
package com.hw.springannotation.conditional;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @Description TODO
* @Author hw
* @Date 2018/11/28 15:02
* @Version 1.0
*/
public class WindowsConditional implements Condition {
/**
* Determine if the condition matches.
*
* @param context 判断条件使用的上下文环境
* @param metadata 当前标注了该注解的注释信息
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO: 2018/11/28 是否是Windows操作系统
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Windows")) {
return true;
}
return false;
}
}
7.4 运行测试类
@Test
public void test3() {
String[] names = applicationContext.getBeanNamesForType(Pension.class);
for (String name : names) {
System.out.println(name);
}
// 获取操作系统环境变量值 Windows 7
Environment environment = applicationContext.getEnvironment();
String osName = environment.getProperty("os.name");
System.out.println(osName);
Map<String, Pension> map = applicationContext.getBeansOfType(Pension.class);
System.out.println(map);
}
运行如下:
我们更改测试类运行的JVM环境,设置-Dos.name=Linux,如图所示:
再次运行如下:
7.4 @Conditional 用法
- 标注在方法上,只有满足条件,该bean才能注册
- 标注在类上,只有满足条件,该类中配置的bean注册才能生效