@Conditional的使用
/**
* conditional 按照一定的条件判断,满足条件给容器中注册bean
* @author xushuai
* @date 2022/3/15 8:07 下午
* @param null
* @return null
*
* 如果是windows系统给容器中注册person1,如果是linux系统,给容器中注册person2
* 可以注解在类上也可以注解在方法上
*/
@Conditional({
MacOsCondition.class
})
@Bean("person2") //给容器注册一个bean ;类型维返回值的类型,id默认用方法名作为id
public Person person2(){
return new Person("wendi","18");
}
@Bean("person1") //给容器注册一个bean ;类型维返回值的类型,id默认用方法名作为id
@Conditional({WindowsOsCondition.class})
public Person person(){
return new Person("xushuai","18");
}
package com.example.paymentdemo.config;
import com.example.paymentdemo.entity.MacOsCondition;
import com.example.paymentdemo.entity.Person;
import com.example.paymentdemo.entity.WindowsOsCondition;
import com.example.paymentdemo.main.MyImportBeanDefinitionRegistrar;
import com.example.paymentdemo.main.MyImportSelector;
import org.springframework.context.annotation.*;
/**
* @author xushuai
* @date 2022年03月12日 5:15 下午
*/
@Configuration
//当标注在类上的时候,满足当前条件,这个类中标注的bean才会生效
@Conditional({WindowsOsCondition.class})
//快速导入组件 id默认是组件的全类名
//可以多个
@Import({Person.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
//@Import(Person.class)
public class Main{
//Specifies the name of the scope to use for the annotated component/bean.
//Defaults to an empty string ("") which implies SCOPE_SINGLETON.
// 默认是单例的 单例的请求ioc容器会调用方法创建对象放到ioc容器中,以后每次获取就是直接从容器中拿
//ioc在容器启动的时候不会创建新对象,多实例每次调用都会获取个新的对象
/**
*懒加载:单实例bean,默认在容器启动的时候创建对象
* 懒加载:容器启动时不创建对象,第一次使用获取时Bean创建对象,并初始化
*/
//ConfigurableBeanFactory.SCOPE_PROTOTYPE, ConfigurableBeanFactory.SCOPE_SINGLETON, 可以配置为多例
// org.springframework.web.context.WebApplicationContext.SCOPE_REQUEST, web环境下可以有request 和session
// org.springframework.web.context.WebApplicationContext.SCOPE_SESSION, value
//还有个全局的global
@Scope(value = "prototype")
@Lazy //懒加载
@Bean("person1") //给容器注册一个bean ;类型维返回值的类型,id默认用方法名作为id
@Conditional({WindowsOsCondition.class})
public Person person(){
return new Person("xushuai","18");
}
/**
* conditional 按照一定的条件判断,满足条件给容器中注册bean
* @author xushuai
* @date 2022/3/15 8:07 下午
* @param null
* @return null
*
* 如果是windows系统给容器中注册person1,如果是linux系统,给容器中注册person2
* 可以注解在类上也可以注解在方法上
*/
@Conditional({
MacOsCondition.class
})
@Bean("person2") //给容器注册一个bean ;类型维返回值的类型,id默认用方法名作为id
public Person person2(){
return new Person("wendi","18");
}
/**
*
* @author xushuai
* @date 2022/3/15 8:39 下午
* @param null
* @return null
* 给容器中注册组件
* 1.包扫描+组件标注注解(@Controller ,@Service ,@Componment) 有局限性,局限于自己写的类
* 2.@bean 导入的第三方包里面的组件
* 3.@Import 快速导入第三方组件
* @Import:容器会自动注册这个组件,id默认全类名
* ImportSelector:返回需要导入的组件的全类名数组;
* ImportBeanDefinitionRegistrar 自己添加组件手动注册bean到容器中
*/
}
package com.example.paymentdemo.entity;
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.context.annotation.Conditional;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @author xushuai
* @date 2022年03月15日 8:20 下午
*/
public class WindowsOsCondition implements Condition {
//conditionContext: 判断条件能使用的上下文环境
//AnnotatedTypeMetsdata :注释信息
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取当前ioc使用的工厂bean
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//获取类加载器
ClassLoader classLoader = context.getClassLoader();
//获取环境
Environment environment = context.getEnvironment();
//获取Bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//判断容器中bean的注册情况
boolean person2 = registry.containsBeanDefinition("person2");
//获取操作系统
String property = environment.getProperty("os.name");
if (property.contains("windows")){
return true;
}
return false;
}
}
package com.example.paymentdemo.main;
import com.example.paymentdemo.entity.Person;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import java.util.Map;
/**
* @author xushuai
* @date 2022年03月15日 8:06 下午
*/
public class ConditionTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.example.paymentdemo");
String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
for (String s : beanNamesForType) {
System.out.println(s);
}
//获取所有bean
Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);
//获取ioc的运行环境
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String property = environment.getProperty("os.name");
System.err.println(property);
}
}
@Import的使用
package com.example.paymentdemo.main;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.function.Predicate;
/**
* @author xushuai
* @date 2022年03月15日 8:45 下午
*/
public class MyImportSelector implements ImportSelector {
//返回值就是要导入到容器中的组件全类名
//AnnotationMetadata:当前标注@Impoert注解的类的所有注解信息(其他注解)
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//把全类名返回
//不能返回null值
return new String[]{"com.example.paymentdemo.entity.Person","com.example.paymentdemo.entity.WindowsOsConfig"};
}
@Override
public Predicate<String> getExclusionFilter() {
return ImportSelector.super.getExclusionFilter();
}
}
package com.example.paymentdemo.main;
import com.example.paymentdemo.entity.Person;
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;
/**
* @author xushuai
* @date 2022年03月15日 8:56 下午
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @author xushuai
* @date 2022/3/15 8:59 下午
* @param importingClassMetadata
* @param registry
* AnnotationMetadata :当前类的注解信息
* BeanDefinitionRegistry :BeanDefinition注册类
* 把所有需要添加到容器中的bean;调用
* BeanDefinitionRegistry.registerBeanDefinition手工注册
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean person = registry.containsBeanDefinition("person");
if (person){
//注册时需要一个beanDefinition的类型
//指定bean的定义信息,bean的类型等信息
RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class);
registry.registerBeanDefinition("person1",beanDefinition);
}
}
}