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);
}