天天看點

二、Spring源碼分析——BeanFactory原創内容,轉載請注明出處1、BeanFactory類圖2、BeanFactory程式設計式實作 3、IOC配置檔案處理(BeanDefinition解析與注冊)4、依賴注入5、總結

原創内容,轉載請注明出處

1、BeanFactory類圖

BeanFactory類圖如下

二、Spring源碼分析——BeanFactory原創内容,轉載請注明出處1、BeanFactory類圖2、BeanFactory程式設計式實作 3、IOC配置檔案處理(BeanDefinition解析與注冊)4、依賴注入5、總結

從上圖可以看出BeanFactory主要實作類是XmlBeanFactory(Spring3.1建議棄用,可以使用DefaultListableBeanFactory和XmlBeanDefinitionReader程式設計實作)和DefaultListableBeanFactory。

2、BeanFactory程式設計式實作

基本IOC容器BeanFactory的程式設計式實作方式大緻可分為三個步驟

1.加載xml資源  Resource定位xml

2.BeanDefinition讀取和加載   BeanDefinitionParserDelegate代理對象去讀取

3.BeanDefinition注冊   BeanDefinitionRegistry去注冊

建立bean.xml,内容如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <bean id="person" class="com.test.bean.Person">
        <property name="name" value="ylxy"/>
        <property name="age" value="25"/>
    </bean>
</beans>      

建立Person類,代碼如下

package com.test.bean;

public class Person {
    
    private String name;
    private int age;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void info(){
        System.out.println("name:"+getName()+" age:"+getAge());
    }
}
           

建立junit測試代碼,内容如下

@Test
	public void testBeanFactory(){
		ClassPathResource resource = new ClassPathResource("bean.xml");
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
		reader.loadBeanDefinitions(resource);
		Person p = bf.getBean("person", Person.class);
		p.info();
	}
           

 最終測試結果如下

二、Spring源碼分析——BeanFactory原創内容,轉載請注明出處1、BeanFactory類圖2、BeanFactory程式設計式實作 3、IOC配置檔案處理(BeanDefinition解析與注冊)4、依賴注入5、總結

 3、IOC配置檔案處理(BeanDefinition解析與注冊)

從程式設計代碼上看,可分以下幾個步驟

1.Resource定位(即Resource包裝spring xml配置檔案)。

2.BeanDefinition解析和注冊(由XmlBeanDefinitionReader類處了解析和注冊)。

3.擷取Bean(由BeanFactory擷取,依賴注入)。

從上面可知BeanDefinition的解析和注冊入口在XmlBeanDefinitionReader的loadBeanDefinitions(Resource resource)方法上。

1.在loadBeanDefinitions方法中,調用該類的doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法。

2.在doLoadBeanDefinitions方法中通過DocumentLoader(實際是DefaultDocumentLoader對象)加載xml檔案成Document類,之後調用該類的registerBeanDefinitions(Document doc, Resource resource)方法去解析加載和注冊BeanDefinition。

3.在registerBeanDefinitions方法中建立DefaultBeanDefinitionDocumentReader對象,并調用registerBeanDefinitions( Document doc, XmlReaderContext readerContext)去解析注冊BeanDefinition,解析時會對不同的xml元素進行不同的解析,比如<import/><alias/><bean/><beans/>等元素。

4.最終實際解析BeanDefinition的實作是建立BeanDefinitionParserDelegate委托對象,調用方法parseBeanDefinitionElement(Element ele)去解析BeanDefinition。

5.注冊對象是在BeanDefinitionReaderUtils.registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)中實作。

BeanDefinition解析實作:調用BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele)去解析xml成BeanDefinition,并将BeanDefinition封裝成BeanDefinitionHolder。

BeanDefinition注冊實作:調用BeanDefinitionRegistry.registerBeanDefinition(String beanName, BeanDefinition beanDefinition),由于DefaultListableBeanFactory實作了該接口的方法,故而實作注冊BeanDefinition是在DefaultListableBeanFactory中。在該類中通過将BeanDefinition存儲到一個HashMap集合中,完成對BeanDefinition的注冊。

4、依賴注入

依賴注入和控制反轉是同一個概念。當某個A javaBean需要B javaBean的引用去協助處理一些事情的時候,在傳統程式設計中,是需要A去new一個B對象。然而在spring中卻不一樣,建立B對象的工作不是由A來new,而是由spring IOC容器去建立,然後将建立的B對象注入到A中。

spring的依賴注入入口也就是BeanFactory的getBean()方法。getBean()方法最後調用doGetBean()方法,即doGetBean()方法是依賴注入的真實入口,代碼如下。

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;

		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			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);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
                        //檢查這個bean是否在目前這個BeanFactory中,如果目前BeanFactory的不包含這個bean,則去父級BeanFactory查找。
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
                                //查找這個BeanDefinition是否有依賴對象,如果有依賴的對象,則IOC容器先建立依賴對象。
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						getBean(dependsOnBean);
						registerDependentBean(dependsOnBean, beanName);
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
                                        //擷取單例對象
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						public Object getObject() throws BeansException {
							try {
                                                                //建立Bean的入口方法
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								// Explicitly remove instance from singleton cache: It might have been put there
								// eagerly by the creation process, to allow for circular reference resolution.
								// Also remove any beans that received a temporary reference to the bean.
								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 '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							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;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}
           

 從上述代碼可以看出建立對象是由DefaultSingletonBeanRegistry的getSingleton方法去建立,然後回調ObjectFactory的getObject方法,ObjectFactory的getObject方法又調用了createBean方法。也就是說實際建立對象的方法是AbstractAutowireCapableBeanFactory類的createBean方法,該方法内又調用doCreateBean去建立Bean。

1.調用createBeanInstance方法去建立BeanWrap(BeanWrap将Bean執行個體包裝了),該方法通過Java反射機制調用Bean的構造函數,完成Bean對象的建立,并将Bean包裝到一個BeanWrap對象中。

2.調用populateBean方法,給bean的屬性初始化,也就是<bean/>标簽中配置的屬性值。

3.調用initializeBean方法,初始化Bean。

  3.1.invokeAwareMethods方法,如果Bean實作了Aware,則調用對應的Aware接口方法。

  3.2.applyBeanPostProcessorsBeforeInitialization方法,如果BeanFactory配置了BeanPostProcessor,則執行BeanPostProcessor的postProcessBeforeInitialization方法。

  3.3.invokeInitMethods方法,如果Bean實作了InitializingBean接口,則調用執行InitializingBean的接口方法。

  3.4.applyBeanPostProcessorsAfterInitialization方法,如果BeanFactory配置了BeanPostProcessor,則執行BeanPostProcessor的postProcessAfterInitialization方法。

4.registerDisposableBeanIfNecessary方法,如果Bean實作了DisposableBean接口或者Bean需要destroy方法,則給Bean注冊DisposableBean功能(即把bean名稱和銷毀方法儲存在一個Map集合中)。

5.getObjectForBeanInstance(sharedInstance, name, beanName, mbd)方法,建立bean完成後,如果建立的bean執行個體是一個FactoryBean(相當于工廠模式的Factory,用來生産Bean執行個體),則會再調用FactoryBean的getObject()方法來生成實際需要的bean執行個體。也就是說如果getBean("factoryBean")會首先擷取FactoryBean執行個體,并且在通過FactoryBean工廠的getObject方法去擷取Bean,如果是getBean(“&factoryBean”),則spring會直接傳回一個FactoryBean執行個體。

5、總結

對于BeanDefinition的解析和注冊過程,首先将xml配置檔案加載進Resource中,然後将Resource解析成Document對象,最後通過BeanDefinitionParserDelegate委托對象去解析Document對象,并将解析的BeanDefinition包裝成BeanDefinitionHolder。最後通過BeanDefinitionRegistry接口将BeanDefinition存儲到HashMap集合中,以完成BeanDefinition的的注冊,具體實作在DefaultListableBeanFactory類中,該類實作了BeanDefinitionRegistry接口。

對于依賴注入,spring主要是使用Java的反射機制來建立bean對象,并為bean進行一些初始化操作。

源代碼如附件