天天看點

BeanFactory

BeanFactory接口Spring架構用來盛放Beans最基礎最泛化的接口。相比之下,其子類如ListableBeanFactorty或ConfigureableBeanFactory都是有更确切目标的接口。Spring中,每一個盛放Bean的容器類都應該實作此接口,并且用唯一的id來辨別每一個Bean。

此類主要提供了從容器中通過類型,名字來擷取Bean的方法。以及通過名字類型來查詢對應Bean是否是單例等資訊的方法。

通常來說,使用Spring的依賴注入(DI)體系來配置Bean要比使用BeanFactory的lookUp方式來的好。Spring DI體系的實作就是基于此接口及其子類接口的。BeanFactory 一般會從配置源(如XML檔案)中加載bean的定義,并通過org.springframework.beans包下的類來對其進行配置。但是此接口并沒有限制必須要從那個資料源中來擷取Bean。你可以實作此接口來從LDAP、RDBMS、XML、Properties甚至直接使用代碼new出來一個都沒有問題。隻要滿足你的需求。

BeanFactory接口有兩個直接子接口,ListableBeanFactory和HierarchicalBeanFactory。如果一個類實作了HierarchicalBeanFactory接口,那麼BeanFactory接口中的這些方法,原則上除了調用本類中的方法,還應該檢查其父BeanFactory中是否有滿足要求,當然具體政策還是由實作者來定,隻是這樣更加符合語義。

BeanFactory的具體實作類還應該支援目前Spring提供的,在Bean的各個生命階段用來對其進行初始化或者銷毀的接口。目前(4.1.2版本)中,Spring提供的所有支援在Bean生命周期内調用的初始化的方法有:

* <li>BeanNameAware's {@code setBeanName}
 * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>BeanFactoryAware's {@code setBeanFactory}
 * <li>EnvironmentAware's {@code setEnvironment}
 * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>ResourceLoaderAware's {@code setResourceLoader}
 * (only applicable when running in an application context)
 * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
 * (only applicable when running in an application context)
 * <li>MessageSourceAware's {@code setMessageSource}
 * (only applicable when running in an application context)
 * <li>ApplicationContextAware's {@code setApplicationContext}
 * (only applicable when running in an application context)
 * <li>ServletContextAware's {@code setServletContext}
 * (only applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
 * <li>InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors           

Spring提供的在BeanFactory銷毀前調用的方法有

<ol>
 * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
 * <li>DisposableBean's {@code destroy}
 * <li>a custom destroy-method definition
 * </ol>           

好了,接下來看下該接口的源碼吧。接口中的方法肯定不會有邏輯的,這裡隻是看下Spring提倡該接口中的方法怎麼用。

public interface BeanFactory {

    /**
     * 此符号在Spring中用以區分由FactoryBean建立出來的Bean和FactoryBean本身
     * 假設 myJndiObject 是一個 FactoryBean, 那麼 &myJndiObject
     * 将會傳回工廠本身,而不是由工廠建立的bean
     */
    String FACTORY_BEAN_PREFIX = "&";


    /**
     * 傳回指定參數那麼指定的Bean
     * 此方法允許BeanFactory參照單例或者原型模式來傳回Bean,例如如果使用者在配置Bean的時候,指定了
     * Scope是Prototype的,那麼沒調一次此方法,都會傳回一個name對應的新生成的Bean。
     * 如果參數name用的是Bean對應的别名,在查找的時候會轉換成全限定的名稱
     * 如果本BeanFactory執行個體中找不到此name對應的Bean,那麼去其父BeanFactory中找
     */
    Object getBean(String name) throws BeansException;

    /**
     * 和getBean(String)此方法功能相同,不過在此基礎上提供了類型檢查。如果BeanFactory中的Bean和所要求的Bean類型
     * 不同,會抛出BeanNotOfRequiredTypeException。requiredType可以是BeanFactory中所存Bean的父類或接口
     */
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    /**
     * 傳回唯一符合參數所指定類型的Bean。此方法和ListableBeanFactory的by-type Bean查找方式可能會
     * 有功能上的重合。但是BeanFactory的實作類也有可能将此方法實作為針對所指定類型的by-name查找(類
     * 的首字母小寫定位Bean的name)。ListableBeanFactory和BeanFactoryUtils中包含更多查找Bean的方法
     */
    <T> T getBean(Class<T> requiredType) throws BeansException;

    /**
     * 傳回參數中指定name的Bean,同時此方法允許你顯式的的指定建立Bean時傳遞給構造方法或者工廠Bean的參數,以覆寫
     * Bean定義中預設參數
     * @throws NoSuchBeanDefinitionException if there is no such bean definition
     * @throws BeanDefinitionStoreException if arguments have been given but
     * the affected bean isn't a prototype
     * @throws BeansException if the bean could not be created
     */
    Object getBean(String name, Object... args) throws BeansException;

    /**
     * 和getBean(String name, Object... args)此方法類似,隻不過不是指定的bean的名字,而是類型。
     */
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;


    /**
     * 檢測此BeanFactory是否包含指定名字的Bean
     * 如果給定參數是Bean的别名,它會被轉換成其對應的全限定名稱。
     * 如果實作類中實作的是HierarchicalBeanFactory,在本BeanFactory中找不到的話,會去父BeanFactory中查找。
     * 如果在此BeanFactory中有指定名字的Bean,不論該Bean是否是抽象類,也不論此類是否建立好(lazy load)
     * 是以即使此方法傳回了true,也不表示getBean方法就一定能從容器中得到該name對應的Bean
     */
    boolean containsBean(String name);

    /**
     * 檢測指定name的Bean是否是單例的,如果是的話,getBean方法調用,将一直傳回同一個引用。
     * 但是如果此方法傳回了false,并不意味着Bean就一定是單例的,它還有可能是request或者session作用于的
     * 如果确實想檢測指定bean是否是單例的請使用isPrototype方法
     * 支援别名查找
     * 支援向父BeanFactory查找
     */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    /**
     * 檢測指定name的Bean的scope是否是prototype的。此方法傳回ture則Bean一定不是單例,每次調用
     * getBean方法都會傳回一個新的執行個體。如果此方法傳回false并不代表對應Bean一定是單例,
     * 其作用域可能是request或者session的。簡單來說就是,想判斷一個Bean是單例的話調用isSingleton
     * ,想判斷是否是prototype的話,調用isPrototype。
     * 支援别名查找
     * 支援向上查找
     */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    /**
     * 檢查給定name的Bean的類型是否比對指定的類型,更确切的說,檢測通過指定參數名字調用getBean方法
     * 傳回的Bean是否能指定給參數中指定類型的變量
     * 支援别名
     * 支援向上查找
     */
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 和isTypeMatch(String name, ResolvableType typeToMatch)方法功能一樣
     * 支援别名
     * 支援向上查找
     */
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 查詢指定名字的Bean的類型。如果指定的Bean是FactoryBean的話,則傳回FactoryBean建立的對象的類型。
     * 類似于FactoryBean的getObjectType
     */
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    /**
     * 查詢指定名字對應Bean的所有别名。
     * 在使用所有這些傳回的别名調用getBean方法時,都将傳回同一種Bean。
     * 如果參數本身就是别名,那麼該方法會傳回其全限定名和所有的别名,并且,全限定名稱在數組的第一位
     * 支援向上查找
     */
    String[] getAliases(String name);

}           

繼續閱讀