Spring註解開發[email protected] , FacotryBean 註冊
目錄
@ComponentScan註解用於掃描自己寫的類(@Controller,@Service,@Component,@Repository),用於加入IOC容器中
@Bean 可以把其他包或者自己寫的類加到IOC容器中
@Import 也可以辦到Bean類似的功能,快速匯入IOC容器中,id預設是全類名
一、@Import 手動注入bean
可以傳入三種引數,
- 直接傳入需要加入IOC的bean的類,
- 使用Importselect ,
- 使用ImportBeanDefinitionRegistrar
[email protected] bean直接傳入IOC
配置類:
@Configuration
@Import(Car.class) //這裡可以傳入一個數組
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
}
測試類:
public class TestAnotation { public static void main(String[] args) { AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class); String[] beanDefinitionNames = configApplicationContext.getBeanDefinitionNames(); Arrays.stream(beanDefinitionNames).forEach(bean -> System.out.println(bean)); } }
結果顯示:@import是全類名,bean就是定義的類名,配置類也會放到容器中
org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig com.wusu.annotation.Car user01
2. @Import ImportSelector 介面
ImportSelector 這個是一個介面,其中的方法只有一個,相當於同時傳入多個Bean,可以再這個實現類做一些判斷
需要返回匯入元件的全類名陣列如下:
2.1 實現ImportSelector這個介面,這裡表示要傳入House和Plane兩個類
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//annotationMetadata 表示標註@Import註解的類的註解資訊
//這個方法不能反悔null,否則會丟擲空指標
return new String[]{"com.wusu.annotation.House","com.wusu.annotation.Plane"};
}
}
2.2 配置類 ,獲取到的bean的id同樣是全類名
@Configuration
@Import({Car.class,MyImportSelector.class})
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
}
3. @Import ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar也是一個介面,在其中直接註冊bean ;這種方式可以加很多判斷條件
3.1 實現介面ImportBeanDefinitionRegistrar的類
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
//annotationMetadata 表示標註@Import註解的類的註解資訊
//beanDefinitionRegistry :bean的註冊類,所有的bean都是通過這個類來註冊的
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
boolean user01 = beanDefinitionRegistry.containsBeanDefinition("user01");
boolean b = beanDefinitionRegistry.containsBeanDefinition("com.wusu.annotation.Car");
//這個類是定義bean資訊的,可以加scope,lazy等資訊
RootBeanDefinition beanDefinition = new RootBeanDefinition(Bicycle.class);
if (user01 && b){ //判斷當上面的兩個bean都被註冊的情況下,才會註冊下面這個bean
beanDefinitionRegistry.registerBeanDefinition("bicycle",beanDefinition);
}
}
}
3.2 配置類
@Configuration
@Import({Car.class,MyImportBeanDefinitionRegister.class})
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
}
二、使用FactoryBean(工廠bean) 註冊bean
1)預設獲取到的是工廠bean通過getObject獲取到的bean
2)要獲取工廠bean本身,需要給id前加“&”。
1.先實現FactoryBean
public class MyFactoryBean implements FactoryBean<Car> {
//返回一個Car物件,這個物件會新增到IOC容器中
@Override
public Car getObject() throws Exception {
return new Car();
}
//類的資訊
@Override
public Class<?> getObjectType() {
return Car.class;
}
//控制這個類是否是單例,返回true表示單例,反之是多例
@Override
public boolean isSingleton() {
return true;
}
}
2.配置類配置這個FactoryBean
@Configuration
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
@Bean
public MyFactoryBean myFactoryBean(){
return new MyFactoryBean();
}
}
3.測試類
public class TestAnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = configApplicationContext.getBeanDefinitionNames();
Arrays.stream(beanDefinitionNames).forEach(bean -> System.out.println(bean));
Object bean = configApplicationContext.getBean("myFactoryBean");
System.out.println(bean.getClass()); //這個結果不是myFactoryBean的資訊而是com.wusu.annotation.Car
}
}
如上獲取的結果始終是在Factorybean中宣告的類,如果要獲取當前這個FactoryBean怎麼處理呢
Object bean = configApplicationContext.getBean("&myFactoryBean"); 這個id名前加一個“&”符號,那麼獲取的結果就是com.wusu.annotation.bean.MyFactoryBean
可以看到BeanFactory原始碼中定義了這個符號:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
...
}