Spring IOC之ignoredDependencyInterface
在閱讀Spring原始碼的時候,我曾經遇到了一個方法ignoredDependencyInterface();當時很是困惑,在查閱大量的資料的時候才初步的理解到了這個方法的作用。這篇文章是邁向Spring IOC原始碼的初步。可能在文章中存在個人的偏見或者主觀臆測,希望大家不要留面子,直接指證,我們一起進步吧。好了,我們開始吧!
在這裡我使用的原始碼是Spring4.3.16的原始碼包。
先建立一個Bean吧。
public class SpringBeanExplor {
private String name;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
配置資原始檔:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:spring/spring-dao.xml"/> <bean id="springBeanExplor" class="com.gosaint.domain.SpringBeanExplor"> <property name="name" value="caozg"/> </bean> </beans>
測試獲取Bean
public class BeanTest { @Test public void testBeanLife() throws Exception{ Resource resource=new ClassPathResource("applicationContext.xml"); BeanFactory beanFactory=new DefaultListableBeanFactory(); BeanDefinitionReader bdr=new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory); bdr.loadBeanDefinitions(resource); SpringBeanExplor bean = beanFactory.getBean(SpringBeanExplor.class); System.out.println(bean.getName()); } }
1 讀取資原始檔,返回Resource的過程這裡我暫且不再贅述。
2 上述建立BeanFactory物件的時候,我沒有使用XmlBeanFactory實現,因為這是一個過時的實現。我使用DefaulteListableBeanFacory作為實現。在new的時候開始建立物件,我們可以觀察這個過程中都幹了些什麼。
public DefaultListableBeanFactory() {
super();
}
在DefaultListableBeanFactory的構造器中呼叫了父類的構造器。DefaultListableBeanFactory繼承了AbstractAutowireCapableBeanFactory。這是一個抽象的自動注入的一個Bean容器。當然是從字面理解。我們再來看看它的構造器的實現:
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
AbstractAutowireCapableBeanFactory的父類是AbstractBeanFactory。它沒有實現。交給子類去實現。大家可以看看三者之間的繼承關係,如下圖所示:
再看上述的方法:ignoreDependencyInterface(Class class);這個方法都幹了寫什麼。
/**
* Ignore the given dependency interface for autowiring.
* <p>This will typically be used by application contexts to register
* dependencies that are resolved in other ways, like BeanFactory through
* BeanFactoryAware or ApplicationContext through ApplicationContextAware.
* <p>By default, only the BeanFactoryAware interface is ignored.
* For further types to ignore, invoke this method for each type.
* @see org.springframework.beans.factory.BeanFactoryAware
* @see org.springframework.context.ApplicationContextAware
*/
//上述註釋的翻譯:忽略給定依賴介面的自動裝配,這通常被應用程式上下文用於註冊。
//依賴關係是通過其他方式解決的,比如BeanFactory BeanFactoryAware或ApplicationContext通過ApplicationContextAware
//預設情況下,只有BeanFactoryAware介面被忽略。若要忽略其他型別,請為每種型別呼叫此方法。
public void ignoreDependencyInterface(Class<?> ifc) {
this.ignoredDependencyInterfaces.add(ifc);
}
簡單的說:由於我要建立一個BeanFactory。但是這個過程中我的Bean可能會依賴一些介面,如:BeanNameAware等。這些介面在建立Bean的過程中不會去例項化,而是自動忽略掉這些依賴。為什麼要忽略這些依賴呢?
private final Set<Class<?>> ignoredDependencyInterfaces = new HashSet<Class<?>>();
這貨其實是個Set集合。目前我們存在兩個問題沒有搞清楚
1 為什麼在實現某些介面的時候依賴的介面要自動忽略注入?
2 如何實現忽略注入的?(待續)
關於第一個問題:對於Spring自動建立Bean,但是Bean是無狀態的,也就是說Bean不知道Spring容器BeanFactory的任何信心,包括Bean自己的名稱name,Spring這樣做的目的是為了Spring容器和Bean的解耦,帶來的問題就是Bean的無狀態。那麼Bean要想定製化的做一些操作,就必然要獲取BeanFactory中的資訊,在Spring Bean的生命週期中我們都知道實現一些列介面去觀察Bean建立過程中的一些資訊。這裡的BeanNameAware、BeanfactoryAware、BeanClassLoaderAware這些介面就是獲取Bean的名稱、BeanFactory的資訊以及類載入器的資訊的。因此這裡牽扯到Spring建立bean的方式,正常例項化的bean和對定製化的bean要有所區分,因此Spring正常例項化的Bean就要忽略這個依賴注入放入介面。