Spring 提供的最基本的Ioc容器接口是BeanFactory, 經過BeanFactory能夠獲取bean對象的實例, 但BeanFactory 是怎麼從配置文件裏讀取的bean對象的信息呢?java
下面的代碼是BeanFactory去獲取spring.xml配置的bean的實例:spring
package com.younchen.test; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import com.younchen.model.Person; public class GetBeanTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //Spring IOC 容器之一BeanFactory //獲取資源文件 Resource resource=new ClassPathResource("spring.xml"); //bean工廠 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); //reader XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(beanFactory); //reader去讀取資源文件 reader.loadBeanDefinitions(resource); //獲取bean對象 Person person=(Person) beanFactory.getBean("person"); person.setName("youn"); System.out.println(person.getName()); } }
看一下Resource變量,Spring裏提供了Resource接口,它是抽象資源接口,classpath中的bean.xml ,spring.xml 均可以描述爲抽象資源。數組
Resource 接口有如下的實例:網絡
UrlResource:訪問網絡資源的實現類。ide
ClassPathResource:訪問類加載路徑裏資源的實現類。this
FileSystemResource:訪問文件系統裏資源的實現類。spa
ServletContextResource:訪問相對於 ServletContext 路徑裏的資源的實現類:debug
InputStreamResource:訪問輸入流資源的實現類。code
ByteArrayResource:訪問字節數組資源的實現類。xml
上面的列子中Resource獲取的實例是ClassPathResource,該類用於讀取類加載路徑(classpath)中的spring.xml,接下來建立BeanFactory 這個時候新建立的beanFactory還不能直接使用,由於beanFactory沒有獲取到配置文件信息, 讀取配置文件的工做是由Resource完成,而解析的時候由BeanDefinitionReader來完成。 實例化beanDefinitionReader時須要將beanFactory傳遞進去,目的是將解析後的bean信息傳給beanFactory。 接下來beanDefinitionReader去解析Resource讀取到的配置文件,這一步完成之後beanFactory就能夠工做了,簡單描述步驟就是:
1.建立Ioc容器抽象資源
2.建立一個BeanFactory
3.將配置文件解析器配置給BeanFactory
4.解析器去讀取配置文件
5.BeanFacotory獲取指定的bean對象實例
下面簡單介紹一下ApplicationContext 即上下文, 上面的例子能夠看出BeanFactory並無資源定義的能力,
他須要解析器去解析以後配置給BeanFactory, 而ApplicationContext卻擁有對資源的定義能力,更確切的說 Application包含了BeanFactory ,先看下代碼:
package com.younchen.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.younchen.model.PersonModel; import com.younchen.util.SpringUtil; public class ApplicationContextTest { public static void main(String[] args){ ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml"); PersonModel personModel =(PersonModel) context.getBean("personModel"); personModel.getPerson().setName("黑貓"); personModel.showPersonName(); }
上面的代碼是上下文去獲取配置文件定義的bean對象的實例,能夠經過debug模式跟進去看Application的建立過程,
實例化的過程他會調用refresh方法:
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //...........省略 } }
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()這一句代碼建立並配置BeanFactory,
繼續追蹤會到:
@Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); // ............省略 } } catch (IOException ex) { //..............省略 } }
try語句中第一行代碼 createBeanFactory()方法是建立BeanFactory的一個實例, 再往下走到loadBeanDefinitions(beanFactory)方法 ,loadBeanDefinitions應該比較熟悉了吧? 用來解析配置文件的,代碼以下:
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
這個方法中 首先實例化了BeanDefinitionReader ,以後經過loadBeanDefinitions 方法讀取配置文件 代碼以下:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
到此就完成了 ApplicationContext 內置的BeanFactory的建立,及將配置文件配置給BeanFactory。
當ApplicationContext執行getBean()方法時 實際上執行的是BeanFactory的getBean方法。
以上是Spring上下文獲取配置文件中bean對象的過程,歡迎指正^^