Spring-IOC學習-01 IOC重要的幾個接口定義

IOC容器

IoC容器:的兩個核心功能是(1)完成了完成對象的建立和(2)bean依賴的管理注入......html

spring ioc 容器抽象的的幾個主要接口java

Resource            //資源文件的抽象,xml 、 properties ...
BeanDefinition         //bean的抽象定義 (bean的一些基本信息是不是 抽象、單例、懶加載、做用域...)基本信息
BeanDefinitionReader      //不一樣的資源文件的bean的解析 
BeanFactory           //bean工廠的頂層抽象定義了幾個基礎的方法 getBean() contanisBean() .... 
ApplicationContext       //應用程序上下文

1: Resource 接口spring

實現類:ClasspathResource、   解析classpath下的資源文件
    URLResource、      解析url網絡資源文件namespace
    FileSystemResource、  解析系統資源文件

Spring 提供了一些org.springframework.core.io.Resource接口的實現,能夠幫助咱們快速獲取Resource信息。
1. URLResource
  封裝了java.net.URL:經過URL能夠得到的對象。 
    Resource resource = new UrlResource("file:/D:/java/src/bean.xml");
  Resource resource = new UrlResource("http://127.0.0.1:8080/index.html");
Resource resource = new UrlResource(new URI("http://127.0.0.1:8080/index.html"));  
2.  FileSystemResource
處理java.io.File 本地資源文件
Resource resource = new FileSystemResource("file:C:\bean.xml");
3. ClassPathResource
  獲取classpath下面的Resource
Resource resource = new ClassPathResource("com/resource/bean.xml");
Resource接口的一些經常使用方法:

   2:BeanDefinition 接口 (描述一個bean對象的基本數據結構數據庫

幾個重要的實現
  BeanDefinitionParserDelegate //解析配置文件
      org.springframework.beans.factory.xml.
BeanDefinitionParserDelegate;
                        parseBeanDefinitionElement()...多個重載方法實現bean的定義
  public class ChildBeanDefinition extends AbstractBeanDefinition
public class RootBeanDefinition extends AbstractBeanDefinition 、
public class GenericBeanDefinition extends AbstractBeanDefinition 、
RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition均繼承了AbstractBeanDefiniton,
    
BeanDefinition對象是配置文件中<bean>元素標籤在容器中內部表示形式。
    <bean>元素標籤擁有class、scope、lazy-init等配置屬性。
    BeanDefinition則提供了相應的beanClass、scope、lazyInit屬性。
    BeanDefinition和<bean>中的屬性是一一對應的。  
    其中RootBeanDefinition是最經常使用的實現類、它對應通常性的<bean>元素標籤,
    GenericBeanDefinition是自2.5之後新加入的bean文件配置屬性定義類,是一站式服務類。
    
在配置文件中能夠定義父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而
    沒有父<bean>的<bean>就使用RootBeanDefinition表示。AbstractBeanDefinition對二者共同的類信息進行抽象。

    Spring經過BeanDefinition將配置文件中的<bean>配置信息轉換爲容器的內部表示,並將這些BeanDefiniton註冊到BeanDefinitonRegistry中。
    Spring容器的BeanDefinitionRegistry就像是Spring配置信息的內存數據庫,主要是以map的形式保存,後續操做直接從BeanDefinitionRegistry中讀取配置信息。
    通常狀況下,BeanDefinition只在容器啓動時加載並解析,除非容器刷新或重啓,這些信息不會發生變化。
    若是用戶有特殊的需求,也能夠經過編程的方式在運行期調整BeanDefinition的定義。

建立最終的BeanDefinition主要包括兩個步驟:
  1)利用BeanDefinitionReader對配置信息Resource進行讀取,經過XML解析器解析配置信息的DOM對象,簡單地爲每一個<bean>生成對應的BeanDefinition對象。
    可是這裏生成的BeanDefinition多是半成品,由於在配置文件中,咱們可能經過佔位符變量引用外部屬性文件的屬性,這些佔位符變量在這一步尚未被解析出來。

  2)利用容器中註冊的BeanFactoryPostProcessor對半成品的BeanDefinition進行加工處理,
    將以佔位符表示的配置解析爲最終的實際值,這樣半成品的BeanDefinition就爲成品的BeanDefinition。

   3:BeanDefinitionReader 接口將配置信息轉換程BeanDefinition編程

BeanDefinitionReader將外部資源對象描述的bean定義統一轉化爲統一的內部數據結構BeanDefinition

主要實現類:
  XmlBeanDefinitionReader
用來讀取xml描述配置的bean對象。
PropertiesBeanDefinitionReader、
用來解析 ×.properties文件描述配置的bean對象。
最後都會 registerBeanDefinitions(...) 註冊解析到的bean對象到map

 4:BeanFactory  接口 (bean的工廠)緩存

主要方法
protected
Object doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException { //bean name處理,去除FactoryBean前綴等 final String beanName = transformedBeanName(name); Object bean = null; //先從singleton緩存中查看是否已經實例化過該Bean,根據是否有緩存分爲兩個分支分別處理 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 分支一,若緩存中獲取到了而且該BeanDefinition信息代表該bean是singleton的,直接將獲取到的緩存Bean //(有多是半成品)交給getObjectForBeanInstance處理 //調用getObjectForBeanInstance處理 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }else { // 分支二:沒有緩存,則須要從頭實例化該bean // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName);} // 檢查BeanDefinition是否在當前工廠或父工廠 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (args != null) { // 父工廠getBean return parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } //將bean加入「正在建立」的集合,完成後會remove,對應afterSingletonCreation/afterPrototypeCreation方法 if (!typeCheckOnly) { markBeanAsCreated(beanName); } final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 解決依賴關係,將依賴的bean提早實例化 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (int i = 0; i < dependsOn.length; i++) { String dependsOnBean = dependsOn[i]; getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // 這裏又須要根據bean的類型分爲三種狀況:singleton、prototype、request/session if (mbd.isSingleton()) { //經過自定義ObjectFactory實例化Bean,此結果多是半成品(是FactoryBean等) sharedInstance = getSingleton(beanName, new ObjectFactory() { public Object getObject() throws BeansException { try { //真正實例化裝配的邏輯在createBean方法中 return createBean(beanName, mbd, args); } catch (BeansException ex) { //顯式地刪除實例從單緩存:它可能已經把那裏  
             //熱切的建立過程,容許循環引用的決議。  
             //刪除任何bean,獲得一個臨時bean的引用。
destroySingleton(beanName); throw ex; } } }); //上一步半成品的Bean交給getObjectForBeanInstance方法處理 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); //真正實例化裝配的邏輯在createBean方法中 prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } //上一步半成品的Bean交給getObjectForBeanInstance方法處理 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { //request、session 的bean String scopeName = mbd.getScope(); final Scope scope = (Scope) this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory() { public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { //真正實例化裝配的邏輯在createBean方法中 return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); //上一步半成品的Bean交給getObjectForBeanInstance方法處理 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return bean; }

建立bean的步驟:
  檢查Bean緩存,已經有緩存的Bean對象(有多是半成品)則交給getObjectForBeanInstance方法處理、  
  不然先根據Bean的生命週期類型分別實例化,每種狀況大體都分兩步,
    第一步都交給createBean方法生產一個半成品的bean對象,
    而後一樣是將半成品的bean交給getObjectForBeanInstance方法

ps:爲何createBean方法建立完的bean是半成品,該半成品交給getObjectForBeanInstance()方法後執行了什麼操做?
5:ApplicationContext 接口

public interface ApplicationContext extends EnvironmentCapable,網絡

                          ListableBeanFactory,      //beanFactorysession

                          HierarchicalBeanFactory,     //beanFactory
                          MessageSource,               //處理消息的基本接口 能夠實現國際化....數據結構

                          ApplicationEventPublisher,   //事件監聽ide

                          ResourcePatternResolver {    //資源處理

主要實現類

  ClasspathXmlApplicationContext,

  FileSystemXmlApplicationContext,

  WebApplicationContext  Web上下文容器 (ServletContext)

  //初始化過程 ClasspathXmlApplicationContext爲例

1.把配置xml文件轉換成resource。resource的轉換是先經過ResourcePatternResolver來解析可識別格式的配置文件的路徑

(如"classpath*:"等),若是沒有指定格式,默認會按照類路徑的資源來處理。
2.利用XmlBeanDefinitionReader完成對xml的解析,將xml Resource裏定義的bean對象轉換成統一的BeanDefinition。
3.將BeanDefinition註冊到BeanFactory,完成對BeanFactory的初始化。BeanFactory裏將會維護一個BeanDefinition的Map。

最後在調用 getBean的時候會執行

 public void refresh() throws BeansException, IllegalStateException {  

      ...

      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //建立BeanFactory  

      //會實例化一個XmlBeanDefinitionReader來解析Resource文件。

      ...

.... }太長了不翻譯了

 

 

 

參考文檔:

  1:http://www.neversaydie.cc/spring-ioc-introduce/

  其它參考文章稍後貼出...

相關文章
相關標籤/搜索