Spring学习笔记(二):bean的注册加载
@Conditional条件注册bean
- 场景:向IoC容器注册bean时,当操作系统为Windows时,注册Sansa实例,当操作系统为Linux时,注册Rob实例。
- 解决方案:使用@Conditional注解进行定制化条件选择注册bean。
- 配置类
@Configuration
public class MainConfig {
@Bean("person")
pubic Person person() {
System.out.println("add John to IoC Container,");
return new Person("John", 20);
}
@Condition({WinCondition.calss})
@Bean("Sansa")
public Person Sansa() {
System.out.println("add Sansa to IoC Container");
return new Person("Sansa", 18)
}
@Condition({LinCondition.calss})
@Bean("Rob")
public Person Rob() {
System.out.println("add Rob to IoC Container");
return new Person("Rob", 21);
}
}
- 条件类WinCondition.java,需实现Spring提供的Condition接口
public class WinCondition implements Condition {
/**
ConditionContext:判断条件能使用的上下文环境
AnnotatedTypeMetadata:注释信息
**/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMedata metadata) {
//1.获取IoC容器使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2.获取类加载器
ClassLoader classloader = context.getClassLoader();
//3.获取当前环境信息
Enviroment enviorment = context.getEnviroment();
//4.获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
String property = enviroment.getProperty("os.name");
if (property.contians("Windows")) {
return true;
}
return false;
}
}
- 新建Linux条件类,用来处理操作系统为Linux的bean注册
public class LinCondition implements Condition {
/**
ConditionContext:判断条件能使用的上下文环境
AnnotatedTypeMetadata:注释信息
**/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMedata metadata) {
//1.获取IoC容器使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2.获取类加载器
ClassLoader classloader = context.getClassLoader();
//3.获取当前环境信息
Enviroment enviorment = context.getEnviroment();
//4.获取bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
String property = enviroment.getProperty("os.name");
if (property.contians("linux")) {
return true;
}
return false;
}
}
- 测试类
//打印IoC容器里的所有person实例名
@Test
public void test() {
//声明IoC容器时获取环境
AnnotationConfigApplicationContext anno = new AnnotationConfigApplicationContext(MainConfig.class);
ConfigurableEnviroment enviroment = anno.getEnviroment();
String property = enviroment.getProperty("os.name");
System.out.println(property);//打印当前环境的操作系统
//根据类型获取容器中的所有bean
String[] beanNamesForType = anno.getBeanNamesForType(Person.class);
for(String name : beanNamesForType) {
System.out.println("name");
}
//打印所有bean,把所有对象和ID放入Map中
Map<String, Person> personBean = anno.getBeansOfType(Person.class);
System.out.println("personBean");
}
- 当引入@Conditional注解时,容器可以有选择性地注册bean
@Import注册bean
使用@Import注解来注册已有类(通常用来加载依赖包中的类)
@Import(Targaryen.class, Lannister.class, Baratheon.class)
public class MainConfig {
@Bean("Stark")
public Stark stark() {
return new Stark("Stark", "wolf");
}
}
实现FactoryBean接口来加载bean
- 自定义工厂bean
/*创建一个自定义FactoryBean
* a.默认获取到的是工厂bean调用getObject创建的对象
* b.要获取工厂bean本身,需要在获取bean时前面加“&”
**/
public class StarkFactoryBean implements FactoryBean<Family> {
//容器调用getObject()方法返回对象,把对象放入容器中
//返回一个Family对象,添加到容器中
@Override
public Family getObject() throws Execption {
return new Family();
}
//返回对象类型
@Override
public Class<?> getObjectType() {
return Family.class;
}
//是否为单例,单例:在容器中只保存一份该bean
@Override
public boolean isSingleton() {
return true;
}
}
- 配置类
@Configuration
@Import(Targaryen.class, Lannister.class, Baratheon.class)
public class MainConfig {
@Bean
public StarkFactoryBean starkFactoryBean() {
return new StarkFactoryBean();
}
}
- 获取bean
//获取FactoryBean调用getObject方法返回的bean
Object family = app.getBean("starkFactoryBean");
//获取StarkFactoryBean本身
object starkFactoryBean = app.getBean("&starkFactoryBean");
FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类StarkFactoryBean,就要getBean(&BeanName),在BeanName之前加上&。
总结:bean的几种注册加载方式
- 包扫描+组件标注注解(@Controller、@Service、@Repository、@Component):一般针对自行定义的类
- @Bean:导入第三方类或包的组件
- @Import:快速导入一个组件到容器
- a.@Import,id默认是全类名
- b. ImportSelector接口,返回需要导入的组件的全类名数组
- c.ImportBeanDefinitionRegistrar
- 使用Spring提供的FactoryBean(工厂Bean)
注:FactoryBean与BeanFactory的区别