Spring源码日常笔记(二)

Spring添加Bean的几种方式

Conditional是按照一定的条件注册bean,假设一下,如果我们有这样的需求,在windows条件下只需要注入一部分的bean,在linux系统条件下注入另一部分的bean,这样的话我们就需要用到condition注解.

  • 新建Cap7MainConfig1.java :
@Configuration
public class Cap5MainConfig {
	@Conditional(WinCondition.class)
	@Bean("lison")
	public Person lison(){
		System.out.println("给容器中添加lison.......");
		return new Person("Lison",58);
	}
	@Conditional(LinCondition.class)
	@Bean("james")//bean在容器中的ID为james, IOC容器MAP,  map.put("id",value)
	public Person james(){
		System.out.println("给容器中添加james.......");
		return new Person("james",20);
	}
}

新建WinCondition.java,LinCondition.java类做为条件类, 同时必须得实现spring提供的Confition接口;

public class WinCondition implements Condition{
	/*
	*ConditionContext: 判断条件可以使用的上下文(环境)
	*AnnotatedTypeMetadata: 注解的信息
	*
	*/
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO 是否为WINDOW系统
		//能获取到IOC容器正在使用的beanFactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		//获取当前环境变量(包括我们操作系统是WIN还是LINUX??)
		Environment environment = context.getEnvironment();
		String os_name = environment.getProperty("os.name");
		if(os_name.contains("Windows")){
			return true;
		}
		return false;
	}

}
public class LinCondition implements Condition{
	/*
	*ConditionContext: 判断条件可以使用的上下文(环境)
	*AnnotatedTypeMetadata: 注解的信息
	*
	*/
	@Override
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO 是否为WINDOW系统
		//能获取到IOC容器正在使用的beanFactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		//获取当前环境变量(包括我们操作系统是WIN还是LINUX??)
		Environment environment = context.getEnvironment();
		String os_name = environment.getProperty("os.name");
		if(os_name.contains("linux")){
			return true;
		}
		return false;
	}

}

写一个测试类:

public class Test {

    public static void main(String[] args) {
        ApplicationContext app = new AnnotationConfigApplicationContext(Cap5MainConfig.class);
        Environment environment = app.getEnvironment();
        String name = environment.getProperty("os.name");
        
        System.out.println(name);
        
    }

}

输出结果:
给容器中添加lison…
Windows 10

我使用的电脑是win10 系统,只有 lison 的bean被注入到容器中.
容器可以选择性的注册bean.这就是condition的作用.

@Import注册bean

  • 同样按流程先新建Cap8MainConfig1.java配置类
public class Cat {

}
public class Dog {

}
  • 使用import将dog, cat的bean注册到容器中
@Configuration
@Import(value = { Dog.class,Cat.class })
public class Cap6MainConfig {
	/*
	 * 给容器中注册组件的方式
	 * 1,@Bean: [导入第三方的类或包的组件],比如Person为第三方的类, 需要在我们的IOC容器中使用
	 * 2,包扫描+组件的标注注解(@ComponentScan:  @Controller, @Service  @Reponsitory  @ Componet),一般是针对 我们自己写的类,使用这个
	 * 3,@Import:[快速给容器导入一个组件] 注意:@Bean有点简单
	 *      a,@Import(要导入到容器中的组件):容器会自动注册这个组件,bean 的 id为全类名
	 *      b,ImportSelector:是一个接口,返回需要导入到容器的组件的全类名数组
	 *      c,ImportBeanDefinitionRegistrar:可以手动添加组件到IOC容器, 所有Bean的注册可以使用BeanDifinitionRegistry
	 *          写JamesImportBeanDefinitionRegistrar实现ImportBeanDefinitionRegistrar接口即可
	 *  4,使用Spring提供的FactoryBean(工厂bean)进行注册
	 *     
	 *   
	 */
	//容器启动时初始化person的bean实例
	@Bean("person")
	public Person person(){
		return new Person("james",20);
	}
}

测试下打印的结果:

public class Cap6Test {

    public static void main(String[] args) {
        ApplicationContext app = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
        String[] beanDefinitionNames = app.getBeanDefinitionNames();
        for(String s : beanDefinitionNames){
            System.out.println(s);
        }
    }
}

打印结果如下:
cap6MainConfig
com.enjoy.cap6.bean.Dog
com.enjoy.cap6.bean.Cat
person

可以看出Dog和Cat被注入了进来.

  • ImportSelector可以批量导入组件的全类名数组,自定义逻辑返回需要导入的组件JamesImportSelector.java
    @Import({Dog.class,Cat.class,JamesImportSelector.class})
    新建JamesImportSelector,
public class JamesImportSelector implements ImportSelector{
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata){
		//返回全类名的bean
		return new String[]{"com.enjoy.cap6.bean.Fish","com.enjoy.cap6.bean.Tiger"};
	}
}

新建Fish Tiger类(与建Cat和Dog一样), 这里省略…

Cap6MainConfig 加上注解

@Configuration
@Import(value = { Dog.class,Cat.class,JamesImportSelector.class})
public class Cap6MainConfig {
	//容器启动时初始化person的bean实例
	@Bean("person")
	public Person person(){
		return new Person("james",20);
	}
}

测试下打印的结果:

public class Cap6Test {

    public static void main(String[] args) {
        ApplicationContext app = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
        String[] beanDefinitionNames = app.getBeanDefinitionNames();
        for(String s : beanDefinitionNames){
            System.out.println(s);
        }
    }
}

打印结果如下:
cap6MainConfig
com.enjoy.cap6.bean.Dog
com.enjoy.cap6.bean.Cat
com.enjoy.cap6.bean.Fish
com.enjoy.cap6.bean.Tiger
person

  • ImportBeanDefinitionRegistrar可以手动添加组件到IOC容器, 所有Bean的注册可以使用BeanDifinitionRegistry
	public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * AnnotationMetadata:当前类的注解信息
	 * BeanDefinitionRegistry:BeanDefinition注册类;
	 * 		把所有需要添加到容器中的bean;调用
	 * 		BeanDefinitionRegistry.registerBeanDefinition手工注册进来
	 */
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
		boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
		boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
		//如果里面包含Red和Blue的Bean
		if(definition && definition2){
			//指定Bean定义信息;(Bean的类型,Bean。。。)
			RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
			//注册一个Bean,指定bean名
			registry.registerBeanDefinition("rainBow", beanDefinition);
		}
	}

}

打印结果如下:
在这里插入图片描述

  • 使用spring的FactoryBean(工厂Bean)
    1. 定义一个ColorFactoryBean
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {

	//返回一个Color对象,这个对象会添加到容器中
	public Color getObject() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("ColorFactoryBean...getObject...");
		return new Color();
	}

	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return Color.class;
	}

	//是单例?
	//true:这个bean是单实例,在容器中保存一份
	//false:多实例,每次获取都会创建一个新的bean;
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return false;
	}

}

测试下:

@Test
	public void testImport(){
		printBeans(applicationContext);
		Blue bean = applicationContext.getBean(Blue.class);
		System.out.println(bean);
		
		//工厂Bean获取的是调用getObject创建的对象
		Object bean2 = applicationContext.getBean("colorFactoryBean");
		Object bean3 = applicationContext.getBean("colorFactoryBean");
		System.out.println("bean的类型:"+bean2.getClass());
		System.out.println(bean2 == bean3);
		
		Object bean4 = applicationContext.getBean("&colorFactoryBean");
		System.out.println(bean4.getClass());
	}

打印结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值