1. 程式人生 > >Spring註解開發[email protected] , FacotryBean 註冊

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 = "&";
...
}