【Spring Framework】Spring入門教程(四)—— 如何註冊Bean到OC容器中
註冊Bean到IOC容器大致分為4種:
①、包掃描+元件註解(@Controller、@Service、@Repository、@Component)
針對類是我們自己編寫的情況
②、@Bean註解
針對匯入第三方包裡面的類的情況
③、@Import
針對快速匯入某一個類的情況,如僅僅只是呼叫無參構造建立物件。
1)@Import註解直接匯入
2)ImportSelector手動匯入Bean到容器中
3)ImportBeanDefinitionRegistrar手動註冊bean到容器中
④、FactoryBean(Bean工廠)
-
預設獲取到的是工廠bean呼叫getObject方法建立的物件
-
要獲取工廠bean本身,我們需要給id前面加一個&
(&FactoryBean)
實戰過Spring的人來說,前兩種方式可謂是最常見不過了。而後兩種方式在開發中比較少見,因此本文主要介紹@Import
和FactoryBean
這兩種方式。
@Import方式
@Import註解原始碼:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
Class<?>[] value();
}
通過原始碼我們可以發現,@Import註解只能放置在類上,並且有一個value屬性,是一個Class型別的陣列,我們將需要匯入到IOC容器的Bean的位元組碼放置這個陣列中,spring容器就會通過反射建立物件到ioc容器中。
--測試
--配置類
@Configuration
@Import({Color.class, Red.class})
public class SpringConfig {
}
--單元測試
@Test public void testApplicationContext2() { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } }
--測試結果
ImportSelector方式
ImportSelect是一個介面,介面中有一個抽象方法selectImports,返回值為一個String陣列,
spring會自動將返回的String陣列中的類建立物件到ioc容器中去。
--MyImportSelector程式碼
public class MyImportSelector implements ImportSelector {
// 返回值就是匯入到容器中的元件的全類名
// AnnotationMetadata:封裝了當前標註@Import註解的類的所有註解資訊
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"org.cjw.pojo.Blue", "org.cjw.pojo.Yellow"};
}
}
--配置類
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class})
public class SpringConfig {
}
--單元測試
同上
--測試結果
ImportBeanDefinitionRegistrar
這種方式和ImportSelector方式很類似,都是實現一個介面,然後在重寫的方法中編寫bean的匯入規則。
--MyImportBeanDefinitionRegistrar程式碼
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
// 編寫註冊判斷規則
// 指定Bean的型別,作用域等等
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
// 註冊一個bean到ioc容器中,並指定beanName
beanDefinitionRegistry.registerBeanDefinition("rainBow", beanDefinition);
}
}
--配置類
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class SpringConfig {
--單元測試
同上
--測試結果
FactoryBean
FactoryBean是一個介面,我們需要編寫一個類實現它,並重寫getObject
、getObejctType
、isSingleton
方法。
-
getObject:IOC容器會執行此方法得到Bean,並放到IOC容器中去。
-
getObjectType:獲取Bean的型別。
-
isSingleton:設定Bean是否為單例,返回值為true為單例,false為多例,ioc容器不管理多例的Bean,只負責建立。
Spring與其他框架進行整合的時候使用的就是FactoryBean來建立物件到IOC容器中。
--ColorFactoryBean程式碼
public class ColorFactoryBean implements FactoryBean<Green> {
@Override
public Green getObject() throws Exception {
return new Green();
}
@Override
public Class<?> getObjectType() {
return Green.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
--SpringConfig程式碼
@Configuration
public class SpringConfig {
@Bean
public ColorFactoryBean colorFactoryBean() {
return new ColorFactoryBean();
}
}
--單元測試
@Test
public void testApplicationContext2() {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
Object bean = context.getBean("colorFactoryBean");
System.out.println(bean);
System.out.println(bean.getClass());
}
--測試結果
通過結果我們可以發現,ioc容器確實有ColorFactoryBean這個物件,但是這個物件的本質是一個Green,即是我們需要建立到ioc容器中的bean。因此我們可以得出結論,只要實現了FactoryBean介面的類,spring都會執行它的getObject方法,將建立的物件放入到ioc容器中,spring和第三方框架的整合靠的就是FactoryBean。