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的區別