在进行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注解根据条件进行组件的注入。