作者的其他平台:
| CSDN:blog.csdn.net/qq_41153943
| 知乎:www.zhihu.com/people/1024…
| GitHub:github.com/JiangXia-10…
本文大概1704字,建议阅读10分钟
在进行spring注解开发时,如果对于某个bean生成了多个实例,在进行组件注册的时候会全部注入到IOC的容器当中,比如:
实体类代码:
package com.xinyi.bean;
public class Person {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public Person() {
}
}
配置类代码:
package com.xinyi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.xinyi.bean.Person;
@Configuration
public class MyConfig1 {
@Bean("Lin Sin")
public Person person() {
return new Person("李青",18);
}
@Bean("Yasuo")
public Person person1() {
return new Person("亚索",23);
}
@Bean("Zed")
public Person person2() {
return new Person("劫",32);
}
}
测试类代码:
package com.xinyi.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.xinyi.bean.Person;
import com.xinyi.config.MyConfig1;
public class IOCTest {
@Test
public void test3() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig1.class);
String[] names = applicationContext.getBeanNamesForType(Person.class);
for(String name:names) {
System.out.println(name);
}
Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
System.out.println(persons);
}
}
输出结果:
三个bean的实例都被注入到IOC容器之中,但是在开发过程中并非所有的bean实例都是需要的,Conditional注解则能够根据不同的需求注入不同的bean实例,@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean,@Conditional注解的源码如下:
//此注解可以标注在类和方法上
@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();
}
@Conditional注解既可以使用在类上,也可以使用在方法上。根据Conditional 注解的源码,在Conditional 注解的参数中需要接受一个Condition(条件)数组,实现Condition 接口的matches方法。
@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);
}
通过获取计算机系统的环境注入不同的bean实例,Condition1判断本地系统为windows系统,Condition2判断本地系统如果Linux系统:
package com.xinyi.condition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
//判断是否是windows系统
public class Condition1 implements Condition{
/**
* ConditionContext:判断条件能使用的上下文,这里是角色
* AnnotatedTypeMetadata:当前标注了Condition注解的注释信息
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 判断角色是否是打野
//1.能够获取到ioc容器使用的beanfactory
ConfigurableBeanFactory beanFactory = context.getBeanFactory();
//2、获取类加载器
ClassLoader loader = context.getClassLoader();
//3、获取当前环境信息
Environment environment=context.getEnvironment();
//4、获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
String property = environment.getProperty("os.name");
if(property.contains("Windows")) {
return true;
}
return false;
}
}
package com.xinyi.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
//判断是否是linux系统
public class Condition2 implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("linux")) {
return true;
}
return false;
}
}
给person和person1使用@Conditional注解,并且分别赋值Conditional1和Conditional2,由于本地系统是window10,所以根据Conditional1的条件Lin Sin和未加任何条件的Zed被注入进容器。
package com.xinyi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.xinyi.bean.Person;
import com.xinyi.condition.Condition1;
import com.xinyi.condition.Condition2;
@Configuration
public class MyConfig1 {
//@Scope("prototype")
//默认单实例
@Bean("Lin Sin")
@Lazy
@Conditional(Condition1.class)
public Person person() {
//System.out.println("IOC容器中注入person实例");
return new Person("李青",18);
}
@Conditional(Condition2.class)
@Bean("Yasuo")
public Person person1() {
return new Person("亚索",23);
}
@Bean("Zed")
public Person person2() {
return new Person("劫",32);
}
}
然后右键 run as—>run configurations----->选择Arguments在vm arguments中输入-Dos.name=linux,将运行时的系统环境设为linux系统,则Conditional2的条件Yasuo和未加任何条件的Zed被注入进容器。
@Conditional(Condition1.class)不仅可以作用在方法上还能作用在类上,作用在类上则表示如果满足条件,则类中的所有bean注册都能生效,反之都不能生效。
package com.xinyi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import com.xinyi.bean.Person;
import com.xinyi.condition.Condition1;
import com.xinyi.condition.Condition2;
@Configuration
@Conditional(Condition1.class)
public class MyConfig1 {
//@Scope("prototype")
//默认单实例
@Bean("Lin Sin")
@Lazy
@Conditional(Condition1.class)
public Person person() {
//System.out.println("IOC容器中注入person实例");
return new Person("李青",18);
}
//@Conditional(Condition2.class)
@Bean("Yasuo")
public Person person1() {
return new Person("亚索",23);
}
@Bean("Zed")
public Person person2() {
return new Person("劫",32);
}
}
所有的bean都注入到ioc容器中,再修改计算机环境参数,@Conditional注解条件改为linux,则所有组件都不会注入进容器。
以上就是使用@Conditional注解根据条件进行组件的注入。
最后欢迎关注公众号:1024笔记,免费获取海量学习资源(涵盖视频、源码、文档)!
相关推荐:
- Spring注解(二):@ComponentScan自动扫描组件
- Spring常用注解大全,值得你的收藏!!!
- Spring注解(七):使用@Value对Bean进行属性赋值
- SpringBoot开发Restful风格的接口实现CRUD功能
- 分布式缓存中间件Redis入门