Spring IOC 是Spring最核心的東西,對Bean的管理是Spring的核心,而後其餘功能都是在Bean容器基礎上進行擴展的。Spring容器這塊咱們重點介紹兩個大塊:一個是BeanFactory,一個是ApplicationContext。這二者的關係是包含關係,ApplicationContext包含了BeanFactory功能,同時又擴展了事件,消息,資源等方面的東西。java
從這個類圖層級結構上看主要分爲左右兩大部分,左半部分主要定義了BeanFacotry相關的接口,右半部分主要定義了BeanRegistry相關的接口。git
從這個類圖咱們自上而下逐布分析,該類圖結構很清晰,通常是一個接口對應一個抽象類的相關實現,一直到最後進行融合都集中到DefaultListableBeanFactory。咱們先大致介紹上面的類圖結構,而後在介紹下BeanDefinition,及BeanFactory工做流程。spring
BeanDefinitionRegistry:主要定義了BeanDefinition註冊接口。這個接口的實現就是最後到DefaultListableBeanFactory才實現的。
數組
AliasRegistry:這個頂級接口主要是爲了管理別名的。對應的實現類主要是SimpleAliasRegistry,內部維護了一個map,來維護對應的關係。ide
如今開始介紹BeanFactory主線方面的接口。工具
BeanFactory:這個Factory的頂級接口,主要定義了Factory最重要的接口,好比getBean等。測試
SingletonBeanRegistry:這個接口主要定義了單例bean管理相關的接口,如registerSingleton,getSingleton等。ui
HierarchicalBeanFactory:這個層級BeanFactory主要定義了BeanFactory能夠包含父Factory功能的相關接口。this
ConfigurableBeanFactory:繼承了HierarchicalBeanFactory,這個接口的做用主要是定義了一些Factory的配置接口,好比setBeanClassLoader,setParentBeanFactory,addBeanPostProcessor,等等。採用Builder模式,一步一步組裝Factory。spa
ListableBeanFactory:這個接口的做用主要定義瞭如何枚舉一個Factory中的相關類,而不是經過name一個一個去獲取,好比該接口定了getBeanNamesForType,getBeanNamesForAnnotation,getBeansWithAnnotation等等,都是以數組,集合等方式返回多個知足需求的結果。
AutowireCapableBeanFactory:這個接口主要定義了建立bean,自動注入等相關的接口。
ConfigurableListableBeanFactory:這個接口從名字上看把ConfigurableBeanFactory,ListableBeanFactory,AutowireCapableBeanFactory三個結合融合在一塊兒,並作了擴展主要提供了分析修改bean definitions的工具,和對單例bean的預實例化(preInstantiateSingletons)。這個接口能夠說是上面介紹全部的接口大融合,涵蓋了BeanFactory所需的大部分方法。
具體接口實現
DefaultSingletonBeanRegistry:這個類主要實現了SingletonBeanRegistry,定義了單例bean的註冊獲取功能。內部實現經過ConcurrentHashMap來維護bean實例。
FactoryBeanRegistrySupport:該類繼承DefaultSingletonBeanRegistry,擴展了FactoryBean須要的相關方法。由於FactoryBean是一種特殊的SingletonBean。
AbstractBeanFactory:該類繼承了FactoryBeanRegistrySupport,實現了接口ConfigurableBeanFactory定義的相關功能。
AbstractAutowireCapableBeanFactory:該類繼承了AbstractBeanFactory,同時實現接口AutowireCapableBeanFactory相關功能。
DefaultListableBeanFactory:這個是總的BeanFactory的實現,同時它自己實現了BeanDefinitionRegistry接口定義的功能,並繼承了AbstractAutowireCapableBeanFactory(主要對應ConfigurableListableBeanFactory接口的實現)。
這裏提下XmlBeanFactory:該類擴展了DefaultListableBeanFactory,方便的從xml文檔中讀取bean definitions;該類藉助XmlBeanDefinitionReader實現,做用等同於把XmlBeanDefinitionReader和DefaultListableBeanFactory簡單的包裝。
從上面三大塊對類圖結構的介紹咱們能夠看到spring 採用接口細化,逐級繼承,而後逐級實現相關功能。直到最後所有功能實現。結構清晰,利於擴展及複用。
這裏先介紹下BeanDefinition。BeanDefinition主要描述了一個bean實例。包含範圍(單例or原型),bean Class類型,實例的屬性值,構造參數值等等,能夠說是一個類須要實例化須要的基本元數據。咱們平時在xml配置的bean信息都會轉變爲BeanDefinition。AbstractBeanDefinition做爲BeanDefinition 的抽象實現。而後該類有三個具體的實現類:
ChildBeanDefinition: Bean definition for beans which inherit settings from their parent. Child bean definitions have a fixed dependency on a parent bean definition.(直接從sping文檔中摘取)
RootBeanDefinition: A root bean definition represents the merged bean definition that backs a specific bean in a Spring BeanFactory at runtime. It might have been created from multiple original bean definitions that inherit from each other, typically registered as GenericBeanDefinition . A root bean definition is essentially the 'unified' bean definition view at runtime.(主要是spring運行時內部能夠用來合併多個definition)
GenericBeanDefinition:一站式標準的bean definition。像任何bean definition,它容許爲指定的類添加構造參數值和屬性值。而且能夠指定parentName,靈活的從父Bean definition進行派生。通常來講,用GenericBeanDefinition用來註冊用戶可見的bean definition。父子關係須要預約義的地方 RootBeanDefinition/ChildBeanDefinition。
這裏若是讀者想本身調試運行代碼 能夠直接git clone spring源碼,而後按照導入說明導入便可,不過加載的時間很長。
咱們先定義個class
//先定義一個普通的java類 public class Person { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } //測試代碼 @Test public void testPerson() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); //用Properties拼裝出BeanDefinitions所需的參數值。 Properties p = new Properties(); p.setProperty("yao.(class)", Person.class.getName()); p.setProperty("yao.age", "18"); p.setProperty("yao.name", "robin"); //把p轉化爲beanDefinition並註冊到beanFactory中。 //若是不寫scope,beanFactory默認產生單例bean。 (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p); Person p1 = (Person) lbf.getBean("yao"); Person p2 = (Person) lbf.getBean("yao"); assertTrue("Non null", p1 != null); assertTrue("Singletons equal", p1 == p2); lbf = new DefaultListableBeanFactory(); p = new Properties(); p.setProperty("yao.(class)", Person.class.getName()); p.setProperty("yao.age", "18"); p.setProperty("yao.name", "robin"); //修改scope p.setProperty("yao.(scope)", "prototype"); (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p); p1 = (Person) lbf.getBean("yao"); p2 = (Person) lbf.getBean("yao"); assertTrue("Non null", p1 != null); assertTrue("Prototypes NOT equal", p1 != p2); }
bean生成的簡單過程:先是經過參數值轉化成BeanDefinition,註冊到BeanFactory中,經過getBean獲取具體實例。
下面咱們一步一步debug ,摘取重要代碼:
第一步:registerBeanDefinitions
//類PropertiesBeanDefinitionReader public int registerBeanDefinitions(Map<?, ?> map, String prefix, String resourceDescription) throws BeansException { --------代碼省略 具體可去看spring源碼----- String keyString = (String) key; if (keyString.startsWith(prefix)) { --------代碼省略 具體可去看spring源碼----- if (sepIdx != -1) { //從property中截取咱們的beanName String beanName = nameAndProperty.substring(0, sepIdx); //判斷咱們註冊容器中是否有該bean if (!getRegistry().containsBeanDefinition(beanName)) { // If we haven't already registered it... registerBeanDefinition(beanName, map, prefix + beanName, resourceDescription); ++beanCount; } } --------代碼省略 具體可去看spring源碼----- } } return beanCount; } protected void registerBeanDefinition(String beanName, Map<?, ?> map, String prefix, String resourceDescription) throws BeansException { String className = null; String parent = null; //默認的scope 主要是這個代碼 String scope = GenericBeanDefinition.SCOPE_SINGLETON; boolean isAbstract = false; //是否延遲初始化 boolean lazyInit = false; ConstructorArgumentValues cas = new ConstructorArgumentValues(); MutablePropertyValues pvs = new MutablePropertyValues(); //遍歷咱們添寫的屬性值 name age 類名字等待。 for (Map.Entry<?, ?> entry : map.entrySet()) { String key = StringUtils.trimWhitespace((String) entry.getKey()); if (key.startsWith(prefix + SEPARATOR)) { String property = key.substring(prefix.length() + SEPARATOR.length()); //從map中解析咱們的className if (CLASS_KEY.equals(property)) { className = StringUtils.trimWhitespace((String) entry.getValue()); } else if (PARENT_KEY.equals(property)) { parent = StringUtils.trimWhitespace((String) entry.getValue()); } else if (ABSTRACT_KEY.equals(property)) { String val = StringUtils.trimWhitespace((String) entry.getValue()); isAbstract = TRUE_VALUE.equals(val); } //解析scope else if (SCOPE_KEY.equals(property)) { // Spring 2.0 style scope = StringUtils.trimWhitespace((String) entry.getValue()); } // else if (SINGLETON_KEY.equals(property)) { // Spring 1.2 style String val = StringUtils.trimWhitespace((String) entry.getValue()); scope = ((val == null || TRUE_VALUE.equals(val) ? GenericBeanDefinition.SCOPE_SINGLETON : GenericBeanDefinition.SCOPE_PROTOTYPE)); } else if (LAZY_INIT_KEY.equals(property)) { String val = StringUtils.trimWhitespace((String) entry.getValue()); lazyInit = TRUE_VALUE.equals(val); } //構造參數 else if (property.startsWith(CONSTRUCTOR_ARG_PREFIX)) { if (property.endsWith(REF_SUFFIX)) { int index = Integer.parseInt(property.substring(1, property.length() - REF_SUFFIX.length())); cas.addIndexedArgumentValue(index, new RuntimeBeanReference(entry.getValue().toString())); } else { int index = Integer.parseInt(property.substring(1)); cas.addIndexedArgumentValue(index, readValue(entry)); } } else if (property.endsWith(REF_SUFFIX)) { // This isn't a real property, but a reference to another prototype // Extract property name: property is of form dog(ref) property = property.substring(0, property.length() - REF_SUFFIX.length()); String ref = StringUtils.trimWhitespace((String) entry.getValue()); // It doesn't matter if the referenced bean hasn't yet been registered: // this will ensure that the reference is resolved at runtime. Object val = new RuntimeBeanReference(ref); pvs.add(property, val); } else { // 類實例自己須要的正常屬性值 pvs.add(property, readValue(entry)); } } } --------代碼省略 具體可去看spring源碼----- if (parent == null && className == null && !beanName.equals(this.defaultParentBean)) { parent = this.defaultParentBean; } try { //經過utils工具建立一個GenericBeanDefinition AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition( parent, className, getBeanClassLoader()); //組裝解析到的屬性值 bd.setScope(scope); bd.setAbstract(isAbstract); bd.setLazyInit(lazyInit); bd.setConstructorArgumentValues(cas); bd.setPropertyValues(pvs); //註冊到beanFactory中,這裏的registry其實就是DefaultListableBeanFactory,添加到其維護的 //ConcurrentHashMap中 getRegistry().registerBeanDefinition(beanName, bd); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(resourceDescription, beanName, className, ex); } catch (LinkageError err) { throw new CannotLoadBeanClassException(resourceDescription, beanName, className, err); } }
第二步 獲取bean
//類AbstractBeanFactory protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // 先去緩衝中取 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //去父factory獲取 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { --------代碼省略 具體可去看spring源碼----- return xxxxxx; } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { //前面提到的RootBeanDefinition 能夠用來合併多個definition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. --------代碼省略 具體可去看spring源碼----- // Create bean instance. //單例 if (mbd.isSingleton()) { //先是去緩衝取,取不到在createBean,這裏就不跟進去了層級還很深。主要是建立bean, //把咱們配置的屬性值都注入進去 ,而後bean緩衝起來 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //原型和單例沒有太大的區別,主要是是否緩衝區實例,原型每次都建立新的實例 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); 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); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } --------代碼省略 具體可去看spring源碼----- return (T) bean; }
基本大概從beanFactory獲取bean 就是這個過程。
類圖
從ApplicationContext和BeanFactory類圖中能夠看出它們的頂級接口大部分是相同的,只是ApplicationContext接口更多一些。ApplicationContext的實現類實際上是包裝了DefaultListableBeanFactory類着一點能夠從其代碼能夠看出
全部的有關bean的獲取等操做都會委託到DefaultListableBeanFactory
ApplicationContext多了MessageSource,ApplicationEventPulisher,ResourceLoader等接口。
這裏篇幅比較長了,不在詳細介紹ApplicationContext接口。
IOC 容器 對bean的主要操做就是這樣。