按照一定条件进行判断,满足条件给容器注册Bean
参数:Condition数组
写在方法上:
示例:根据操作系统注册Bean
@Conditional(WindowsCondition.class)//判断条件
@Bean("bill")//windows系统注册该Bean
public Person person01(){
return new Person("Bill Gates", 62);
}
@Conditional(LinuxCondition.class)
@Bean("linus")//linux系统注册该Bean
public Person person02(){
return new Person("Linus", 48);
}
定义两个条件:
package pers.zhang.condition;
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;
/**
* @author zhang
* @date 2019/12/1 - 16:03
*/
//判断是否为linux系统
public class LinuxCondition implements Condition {
/*
参数ConditionContext:判断条件所使用上下文环境
参数AnnotatedTypeMetadata:标注了Conditional的注释信息
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//可以获取Bean的创建工厂
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//可以获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//可以获取Bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//获取环境信息
Environment environment = conditionContext.getEnvironment();
//获取操作系统
String system = environment.getProperty("os.name");
if(system.contains("linux")){
return true;
}
return false;
}
}
package pers.zhang.condition;
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;
/**
* @author zhang
* @date 2019/12/1 - 16:03
*/
//判断是否为windos系统
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//也可以判断容器中是否包含某个Bean
//BeanDefinitionRegistry registry = conditionContext.getRegistry();
//registry.containsBeanDefinition("xxx")
//获取环境信息
Environment environment = conditionContext.getEnvironment();
//获取操作系统
String system = environment.getProperty("os.name");
if(system.contains("Windows")){
return true;
}
return false;
}
}
测试:
@Test
public void printBeans(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
String[] definitionNames = ac.getBeanDefinitionNames();
for(String name : definitionNames){
System.out.println(name);
}
}
写在类上:
满足当前条件,这个类中配置的所有Bean注册才能生效
@Import 注解可以普通类导入到 IoC容器中。
想要让一个普通类接受 Spring 容器管理,有以下方法
第一种方式:
@Import(要导入到容器中的组件)
//参数为数组,id默认为全类名
示例:
package pers.zhang.bean;
public class Color {
}
package pers.zhang.bean;
public class Red {
}
package pers.zhang.config;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import pers.zhang.bean.Color;
import pers.zhang.bean.Person;
import pers.zhang.bean.Red;
import pers.zhang.service.BookService;
@Configuration
@ComponentScan("pers.zhang")
@Import({Color.class, Red.class})//导入组件
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,方法名作为id;也可以指定id:@Bean("id")
@Bean
@Scope("singleton")
@Lazy
public Person person(){
return new Person("zhangsan", 18);
}
}
@Test
public void printBeans(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
String[] definitionNames = ac.getBeanDefinitionNames();
for(String name : definitionNames){
System.out.println(name);
}
}
第二种方式:实现ImportSelector
返回需要导入的组件的全类名的数组
package pers.zhang.bean;
public class Yellow {
}
package pers.zhang.bean;
public class Blue {
}
实现ImportSelector
package pers.zhang.condition;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author zhang
* @date 2019/12/1 - 15:22
*/
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
//返回值:就是要导入到容器中的组件全类名
//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
//可以返回空数组,不可以返回null,会报空指针异常!
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"pers.zhang.bean.Blue", "pers.zhang.bean.Yellow"};
}
}
添加到Import参数中
@Import({Color.class, Red.class, MyImportSelector.class})
第三种方式:实现ImportBeanDefinitionRegistrar
手动注册方式,可以指定Bean的定义信息
package pers.zhang.bean;
public class Green {
}
实现ImportBeanDefinitionRegistrar:
package pers.zhang.condition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import pers.zhang.bean.Green;
/**
* @author zhang
* @date 2019/12/1 - 15:36
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/*
参数:AnnotationMetadata,当前类注解信息
参数:BeanDefinitionRegistry,BeanDefinition注册类
把所有需要添加到容器中的Bean;调用BeanDefinitionRegistry.registerBeanDefinition手动注册进来
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
boolean blue = beanDefinitionRegistry.containsBeanDefinition("pers.zhang.bean.Blue");
boolean red = beanDefinitionRegistry.containsBeanDefinition("pers.zhang.bean.Red");
if(blue && red){//如果包含蓝色和红色就注册绿色
//指定Bean的定义信息(类型,Scope)
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Green.class);
//可以指定Bean名
beanDefinitionRegistry.registerBeanDefinition("green", rootBeanDefinition);
}
}
}
修改Import参数:
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})