提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着对springboot的简单使用后,对springboot源码中的一些注解不太明白,为了之后开启springboot源码读取的困难,做一些预备工作,来开始了解和记录一些遇到的一部分注解吧
提示:以下是本篇文章正文内容,下面案例可供参考
一、@Conditional注解是什么?
@Conditional注解是spring4里面新添加的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册bean。
二、概述
1.@conditional注解定义
代码如下(示例):
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
2.condition
我们点进去后,发现他是个接口,只有一个方法。
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
3.condtionContext
它持有不少有用的对象,可以用来获取很多系统相关的信息,来丰富条件判断,接口定义如下:
public interface ConditionContext {
/**
* 获取Bean定义
*/
BeanDefinitionRegistry getRegistry();
/**
* 获取Bean工程,因此就可以获取容器中的所有bean
*/
@Nullable
ConfigurableListableBeanFactory getBeanFactory();
/**
* environment 持有所有的配置信息
*/
Environment getEnvironment();
/**
* 资源信息
*/
ResourceLoader getResourceLoader();
/**
* 类加载信息
*/
@Nullable
ClassLoader getClassLoader();
}
案例
需求:根据当前系统环境的不同实例不同的bean,比如现在是Mac那就是实例一个bean,如果是Windows系统实例另一个bean。
1.SystemBean
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class SystemBean {
/**
* 系统名称
*/
private String systemName;
/**
* 系统code
*/
private String systemCode;
}
2.通过Configuration配置实例化bean
@Slf4j
@Configuration
public class ConditionalConfig {
/**
* 如果WindowsCondition的实现方法返回true,则注入这个bean
*/
@Bean("windows")
@Conditional({WindowsCondition.class})
public SystemBean systemWi() {
log.info("ConditionalConfig方法注入 windows实体");
return new SystemBean("windows系统","002");
}
/**
* 如果LinuxCondition的实现方法返回true,则注入这个bean
*/
@Bean("mac")
@Conditional({MacCondition.class})
public SystemBean systemMac() {
log.info("ConditionalConfig方法注入 mac实体");
return new SystemBean("Mac ios系统","001");
}
}
3.WindowsCondition和MacCondition
这两个类都实现了Condition接口,只有matches方法返回true才会实例化当前bean
- WindowsCondition实现类
@Slf4j
public class WindowsCondition implements Condition {
/**
* @param conditionContext:判断条件能使用的上下文环境
* @param annotatedTypeMetadata:注解所在位置的注释信息
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//获得当前系统名
String property = environment.getProperty("os.name");
//包含Windows则说明是windows系统,返回true
if (property.contains("Windows")){
log.info("当前操作系统是:Windows");
return true;
}
return false;
}
}
- MacCondition实现类
@Slf4j
public class MacCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Mac")) {
log.info("当前操作系统是:Mac OS X");
return true;
}
return false;
}
}
3.测试类
/**
* @author xub
* @date 2019/6/13 下午10:42
*/
@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class TestConditionOn {
@Autowired
private SystemBean windows;
@Autowired
private SystemBean mac;
@Test
public void test() {
if (windows != null) {
System.out.println("windows = " + windows);
}
if (mac != null) {
System.out.println("linux = " + mac);
}
}
}
运行结果
通过运行结果可以看出
- 通过配置两个bean,但这里只实例化了一个bean,因为我这边是windows电脑,所以实例化的是windows的SystemBean
- 需要注意一点:我们可以看出mac并不为null,而是window实例化的bean,不管你命名什么,都可以注入这个bean
修改一下配置
这里做一个修改,我们把ConditionalConfig中的这行代码注解掉。
// @Conditonal({WindowsConfig.class})
通过运行结果可以看出,配置类的两个bean都已经注册成功。
注意:当同一个对象被注入两次及以上的时候,那么你在使用当前对象的时候,名称一定是要两个bean名称的一个,否则报错。比如修改为:
@Autowired
private SystemBean windows;
@Autowired
private SystemBean mac;
@Autowired
private SystemBean linux;
在启动时,报错了
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了@condition注解的使用和含义。