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)
- 定義一個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());
}
打印結果如下: