1. 程式人生 > 其它 >【Spring Framework】Spring入門教程(四)—— 如何註冊Bean到OC容器中

【Spring Framework】Spring入門教程(四)—— 如何註冊Bean到OC容器中

註冊Bean到IOC容器大致分為4種:

①、包掃描+元件註解(@Controller、@Service、@Repository、@Component)

針對類是我們自己編寫的情況

②、@Bean註解

針對匯入第三方包裡面的類的情況

③、@Import

針對快速匯入某一個類的情況,如僅僅只是呼叫無參構造建立物件。

1)@Import註解直接匯入

2)ImportSelector手動匯入Bean到容器中

3)ImportBeanDefinitionRegistrar手動註冊bean到容器中

④、FactoryBean(Bean工廠)

  1. 預設獲取到的是工廠bean呼叫getObject方法建立的物件

  2. 要獲取工廠bean本身,我們需要給id前面加一個&(&FactoryBean)

實戰過Spring的人來說,前兩種方式可謂是最常見不過了。而後兩種方式在開發中比較少見,因此本文主要介紹@ImportFactoryBean這兩種方式。

@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是一個介面,我們需要編寫一個類實現它,並重寫getObjectgetObejctTypeisSingleton方法。

  • 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。