在Spring Framework源代碼解析之IOC容器(一)和Spring Framework源代碼解析之IOC容器(二),我們對Spring IOC做了簡單介紹以及熟悉了一些支持IOC的關鍵類,本文將對IOC的依賴注入特性進行解析,歡迎指正。
載入和註冊
在上文中,我們介紹到XmlBeanFactory對資源文件的載入,並最後引出了一個高帥富——ApplicationContext。接著上文來看,其實我們平時最常用的是Application,因為它不僅具備BeanFactory的全部能力,還為應用程序提供了很多的便利,上文已經說過了,它繼承了很多父類,使它可以具備支持國際化、支持多方式定義資源,支持事件等。我們可以認為BeanFactory和Application是兩個層面的IOC容器,而我們平時開發應用程序就是使用Application。Application有很多抽象子類,如AbstractApplicationContext,在該抽象子類下又有很多具體的實現類,如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext等。我們以FileSystemXmlApplicationContext為例,來看看它載入和註冊資源的過程。
首先通過FileSystemXmlApplicationContext來建立IOC容器:
<code>ApplicationContext = new FileSystemXmlApplicationContext(xmlPath);/<code>
調用構造函數:
<code>/**
* Create a new FileSystemXmlApplicationContext, loading the definitions
* from the given XML files and automatically refreshing the context.
* @param configLocations array of file paths
* @throws BeansException if context creation failed
*/
public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}/<code>
實際調用:
<code>public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}/<code>
注意方法refresh(),這裡使用了一個“模板方法”的設計模式,refresh()是一個模板方法,具體實現在FileSystemXmlApplicationContext的若干級父類AbstractXmlApplicationContext中:
<code>public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
synchronized (this.activeMonitor) {
this.active = true;
}
// 這裡需要子類來協助完成資源位置定義,bean 載入和向 IOC 容器註冊的過程
refreshBeanFactory();
............
}/<code>
refresh()方法包含了整個IOC容器的初始化過程,資源的定位由refreshBeanFactory()來實現,而在AbstractXmlApplicationContext中定義了對資源的讀取過程,默認由 XmlBeanDefinitionReader 來讀取:
<code>protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
// 這裡使用 XMLBeanDefinitionReader 來載入 bean 定義信息的 XML 文件
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//這裡配置 reader 的環境,其中 ResourceLoader 是我們用來定位 bean 定義信息資源位置的
///因為上下文本身實現了 ResourceLoader 接口,所以可以直接把上下文作為 ResourceLoader 傳遞給 XmlBeanDefi
nitionReader
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
initBeanDefinitionReader(beanDefinitionReader);
//這裡轉到定義好的 XmlBeanDefinitionReader 中對載入 bean 信息進行處理
loadBeanDefinitions(beanDefinitionReader);
}/<code>
轉到beanDefinitionReader中進行處理:
<code>protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOExcepti
on {
Resource[] configResources = getConfigResources();
if (configResources != null) {
//調用 XmlBeanDefinitionReader 來載入 bean 定義信息。
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}/<code>
完成了載入,我們來分析註冊,來到DefaultListableBeanFactory中,它通過HashMap來持有載入的BeanDefinition:
<code>/** Map of bean definition objects, keyed by bean name */
private final Map<string> beanDefinitionMap = new ConcurrentHashMap<string>();/<string>/<string>/<code>
跟蹤代碼,找到註冊的具體實現類DefaultListableBeanFactoy:
<code>//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
synchronized (this.beanDefinitionMap) {
//這裡檢查是不是有名字相同的BeanDefinition已經在IOC容器中註冊,如果有但不允許覆蓋則拋出異常
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
resetBeanDefinition(beanName);
}
}/<code>
完成了註冊,此時我們就是從容器中使用對象了,萬事具備只欠getBean了。
依賴注入
我們記得在BeanFactory中有一個getBean方法,它其實就是觸發依賴注入的入口,getBean的實現我們具體看看DefaultListableBeanFactory的父類AbstractBeanFactory,看看其中getBean的是如何實現的:
<code>public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}/<code>
接著看doGetBean:
<code>1. protectedT doGetBean(final String name, final Class /<code>requiredType,
<code>2. final Object[] args, boolean typeCheckOnly) throws BeansException {/<code>
<code> 3: /<code>
<code> 4: final String beanName = transformedBeanName(name);/<code>
<code> 5: Object bean;/<code>
<code> 6: /<code>
<code> 7: // Eagerly check singleton cache for manually registered singletons./<code>
<code> 8: // 先從緩存裡面取,處理已經被創建過的單件模式的bean,對這種bean的獲取不需要重複的創建/<code>
<code> 9: Object sharedInstance = getSingleton(beanName);/<code>
<code> 10: if (sharedInstance != null && args == null) {/<code>
<code> 11: if (logger.isDebugEnabled()) {/<code>
<code> 12: if (isSingletonCurrentlyInCreation(beanName)) {/<code>
<code> 13: logger.debug("Returning eagerly cached instance of singleton bean '"/<code>
<code> 14: + beanName/<code>
<code> 15: + "' that is not fully initialized yet - a consequence of a circular reference");/<code>
<code> 16: } else {/<code>
<code> 17: logger.debug("Returning cached instance of singleton bean '"/<code>
<code> 18: + beanName + "'");/<code>
<code> 19: }/<code>
<code> 20: }/<code>
<code> 21: bean = getObjectForBeanInstance(sharedInstance, name, beanName,/<code>
<code> 22: null);/<code>
<code> 23: }/<code>
<code> 24: /<code>
<code> 25: else {/<code>
<code> 26: // Fail if we're already creating this bean instance:/<code>
<code> 27: // We're assumably within a circular reference./<code>
<code> 28: if (isPrototypeCurrentlyInCreation(beanName)) {/<code>
<code> 29: throw new BeanCurrentlyInCreationException(beanName);/<code>
<code> 30: }/<code>
<code> 31: /<code>
<code> 32: // Check if bean definition exists in this factory./<code>
<code> 33: BeanFactory parentBeanFactory = getParentBeanFactory();/<code>
<code> 34: if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {/<code>
<code> 35: // Not found -> check parent./<code>
<code> 36: String nameToLookup = originalBeanName(name);/<code>
<code> 37: if (args != null) {/<code>
<code> 38: // Delegation to parent with explicit args./<code>
<code> 39: return (T) parentBeanFactory.getBean(nameToLookup, args);/<code>
<code> 40: } else {/<code>
<code> 41: // No args -> delegate to standard getBean method./<code>
<code> 42: return parentBeanFactory/<code>
<code> 43: .getBean(nameToLookup, requiredType);/<code>
<code> 44: }/<code>
<code> 45: }/<code>
<code> 46: /<code>
<code> 47: if (!typeCheckOnly) {/<code>
<code> 48: markBeanAsCreated(beanName);/<code>
<code> 49: }/<code>
<code> 50: // 這裡根據bean的名字取得BeanDefinition/<code>
<code> 51: final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);/<code>
<code> 52: checkMergedBeanDefinition(mbd, beanName, args);/<code>
<code> 53: /<code>
<code> 54: // Guarantee initialization of beans that the current bean depends/<code>
<code> 55: // on./<code>
<code> 56: // 取當前bean的所有依賴的bean,這樣會觸發getBean的遞歸調用,直至取到一個沒有任何依賴的bean為止/<code>
<code> 57: String[] dependsOn = mbd.getDependsOn();/<code>
<code> 58: if (dependsOn != null) {/<code>
<code> 59: for (String dependsOnBean : dependsOn) {/<code>
<code> 60: getBean(dependsOnBean);/<code>
<code> 61: registerDependentBean(dependsOnBean, beanName);/<code>
<code> 62: }/<code>
<code> 63: }/<code>
<code> 64: /<code>
<code> 65: // Create bean instance./<code>
<code> 66: // 這裡創建單例的實例,調用createBean方法/<code>
<code> 67: if (mbd.isSingleton()) {/<code>
<code> 68: sharedInstance = getSingleton(beanName,/<code>
<code> 69: new ObjectFactory<object>() {/<object>/<code>
<code> 70: public Object getObject() throws BeansException {/<code>
<code> 71: try {/<code>
<code> 72: return createBean(beanName, mbd, args);/<code>
<code> 73: } catch (BeansException ex) {/<code>
<code> 74: // Explicitly remove instance from singleton/<code>
<code> 75: // cache: It might have been put there/<code>
<code> 76: // eagerly by the creation process, to allow/<code>
<code> 77: // for circular reference resolution./<code>
<code> 78: // Also remove any beans that received a/<code>
<code> 79: // temporary reference to the bean./<code>
<code> 80: destroySingleton(beanName);/<code>
<code> 81: throw ex;/<code>
<code> 82: }/<code>
<code> 83: }/<code>
<code> 84: });/<code>
<code> 85: bean = getObjectForBeanInstance(sharedInstance, name, beanName,/<code>
<code> 86: mbd);/<code>
<code> 87: }/<code>
<code> 88: // 這裡則是創建prototype bean的地方/<code>
<code> 89: else if (mbd.isPrototype()) {/<code>
<code> 90: // It's a prototype -> create a new instance./<code>
<code> 91: Object prototypeInstance = null;/<code>
<code> 92: try {/<code>
<code> 93: beforePrototypeCreation(beanName);/<code>
<code> 94: prototypeInstance = createBean(beanName, mbd, args);/<code>
<code> 95: } finally {/<code>
<code> 96: afterPrototypeCreation(beanName);/<code>
<code> 97: }/<code>
<code> 98: bean = getObjectForBeanInstance(prototypeInstance, name,/<code>
<code> 99: beanName, mbd);/<code>
<code> 100: }/<code>
<code> 101: /<code>
<code> 102: else {/<code>
<code> 103: String scopeName = mbd.getScope();/<code>
<code> 104: final Scope scope = this.scopes.get(scopeName);/<code>
<code> 105: if (scope == null) {/<code>
<code> 106: throw new IllegalStateException(/<code>
<code> 107: "No Scope registered for scope '" + scopeName + "'");/<code>
<code> 108: }/<code>
<code> 109: try {/<code>
<code> 110: Object scopedInstance = scope.get(beanName,/<code>
<code> 111: new ObjectFactory<object>() {/<object>/<code>
<code> 112: public Object getObject() throws BeansException {/<code>
<code> 113: beforePrototypeCreation(beanName);/<code>
<code> 114: try {/<code>
<code> 115: return createBean(beanName, mbd, args);/<code>
<code> 116: } finally {/<code>
<code> 117: afterPrototypeCreation(beanName);/<code>
<code> 118: }/<code>
<code> 119: }/<code>
<code> 120: });/<code>
<code> 121: bean = getObjectForBeanInstance(scopedInstance, name,/<code>
<code> 122: beanName, mbd);/<code>
<code> 123: } catch (IllegalStateException ex) {/<code>
<code> 124: throw new BeanCreationException(/<code>
<code> 125: beanName,/<code>
<code> 126: "Scope '"/<code>
<code> 127: + scopeName/<code>
<code> 128: + "' is not active for the current thread; "/<code>
<code> 129: + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",/<code>
<code> 130: ex);/<code>
<code> 131: }/<code>
<code> 132: }/<code>
<code> 133: }/<code>
<code> 134: /<code>
<code> 135: // Check if required type matches the type of the actual bean instance./<code>
<code> 136: // 這裡對創建出來bean進行類型的檢查,如果沒有問題,就返回這個新創建的bean/<code>
<code> 137: if (requiredType != null && bean != null/<code>
<code> 138: && !requiredType.isAssignableFrom(bean.getClass())) {/<code>
<code> 139: try {/<code>
<code> 140: return getTypeConverter()/<code>
<code> 141: .convertIfNecessary(bean, requiredType);/<code>
<code> 142: } catch (TypeMismatchException ex) {/<code>
<code> 143: if (logger.isDebugEnabled()) {/<code>
<code> 144: logger.debug(/<code>
<code> 145: "Failed to convert bean '" + name/<code>
<code> 146: + "' to required type ["/<code>
<code> 147: + ClassUtils.getQualifiedName(requiredType)/<code>
<code> 148: + "]", ex);/<code>
<code> 149: }/<code>
<code> 150: throw new BeanNotOfRequiredTypeException(name, requiredType,/<code>
<code> 151: bean.getClass());/<code>
<code> 152: }/<code>
<code> 153: }/<code>
<code> 154: return (T) bean;/<code>
<code> 155: }/<code>
具體創建對象在createBean裡面,來看看createBean:
<code> 1: protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)/<code>
<code> 2: throws BeanCreationException {/<code>
<code> 3: /<code>
<code> 4: if (logger.isDebugEnabled()) {/<code>
<code> 5: logger.debug("Creating instance of bean '" + beanName + "'");/<code>
<code> 6: }/<code>
<code> 7: // Make sure bean class is actually resolved at this point./<code>
<code> 8: resolveBeanClass(mbd, beanName);/<code>
<code> 9: /<code>
<code> 10: // Prepare method overrides./<code>
<code> 11: try {/<code>
<code> 12: mbd.prepareMethodOverrides();/<code>
<code> 13: }/<code>
<code> 14: catch (BeanDefinitionValidationException ex) {/<code>
<code> 15: throw new BeanDefinitionStoreException(mbd.getResourceDescription(),/<code>
<code> 16: beanName, "Validation of method overrides failed", ex);/<code>
<code> 17: }/<code>
<code> 18: /<code>
<code> 19: try {/<code>
<code> 20: // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance./<code>
<code> 21: Object bean = resolveBeforeInstantiation(beanName, mbd);/<code>
<code> 22: if (bean != null) {/<code>
<code> 23: return bean;/<code>
<code> 24: }/<code>
<code> 25: }/<code>
<code> 26: catch (Throwable ex) {/<code>
<code> 27: throw new BeanCreationException(mbd.getResourceDescription(), beanName,/<code>
<code> 28: "BeanPostProcessor before instantiation of bean failed", ex);/<code>
<code> 29: }/<code>
<code> 30: //這裡是創建bean的調用/<code>
<code> 31: Object beanInstance = doCreateBean(beanName, mbd, args);/<code>
<code> 32: if (logger.isDebugEnabled()) {/<code>
<code> 33: logger.debug("Finished creating instance of bean '" + beanName + "'");/<code>
<code> 34: }/<code>
<code> 35: return beanInstance;/<code>
<code> 36: }/<code>
又看doCreateBean,^_^遭不住啊。。
<code> 1: protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {/<code>
<code> 2: // Instantiate the bean./<code>
<code> 3: BeanWrapper instanceWrapper = null;/<code>
<code> 4: if (mbd.isSingleton()) {/<code>
<code> 5: instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);/<code>
<code> 6: }/<code>
<code> 7: if (instanceWrapper == null) {/<code>
<code> 8: instanceWrapper = createBeanInstance(beanName, mbd, args);/<code>
<code> 9: }/<code>
<code> 10: ........./<code>
<code> 11: /<code>
<code> 12: }/<code>
具體創建對象的方法是createBeanInstance:
<code> 1: protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {/<code>
<code> 2: // Make sure bean class is actually resolved at this point./<code>
<code> 3: Class beanClass = resolveBeanClass(mbd, beanName);/<code>
<code> 4: /<code>
<code> 5: if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {/<code>
<code> 6: throw new BeanCreationException(mbd.getResourceDescription(), beanName,/<code>
<code> 7: "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());/<code>
<code> 8: }/<code>
<code> 9: //這裡使用工廠方法對bean進行實例化/<code>
<code> 10: if (mbd.getFactoryMethodName() != null) {/<code>
<code> 11: return instantiateUsingFactoryMethod(beanName, mbd, args);/<code>
<code> 12: }/<code>
<code> 13: /<code>
<code> 14: // Shortcut when re-creating the same bean.../<code>
<code> 15: boolean resolved = false;/<code>
<code> 16: boolean autowireNecessary = false;/<code>
<code> 17: if (args == null) {/<code>
<code> 18: synchronized (mbd.constructorArgumentLock) {/<code>
<code> 19: if (mbd.resolvedConstructorOrFactoryMethod != null) {/<code>
<code> 20: resolved = true;/<code>
<code> 21: autowireNecessary = mbd.constructorArgumentsResolved;/<code>
<code> 22: }/<code>
<code> 23: }/<code>
<code> 24: }/<code>
<code> 25: if (resolved) {/<code>
<code> 26: if (autowireNecessary) {/<code>
<code> 27: return autowireConstructor(beanName, mbd, null, null);/<code>
<code> 28: }/<code>
<code> 29: else {/<code>
<code> 30: return instantiateBean(beanName, mbd);/<code>
<code> 31: }/<code>
<code> 32: }/<code>
<code> 33: /<code>
<code> 34: // Need to determine the constructor.../<code>
<code> 35: //使用構造函數進行實例化/<code>
<code> 36: Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);/<code>
<code> 37: if (ctors != null ||/<code>
<code> 38: mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||/<code>
<code> 39: mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {/<code>
<code> 40: return autowireConstructor(beanName, mbd, ctors, args);/<code>
<code> 41: }/<code>
<code> 42: /<code>
<code> 43: // No special handling: simply use no-arg constructor./<code>
<code> 44: //使用默認的構造函數對bean進行實例化/<code>
<code> 45: return instantiateBean(beanName, mbd);/<code>
<code> 46: }/<code>
來看看使用默認的構造函數對bean進行實例化的代碼instantiateBean:
<code> 1: protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {/<code>
<code> 2: try {/<code>
<code> 3: //使用默認的實例化策略對bean進行實例化,默認的實例化策略是CglibSubclassingInstantiationStrategy,也就是用cglib來對bean進行實例化/<code>
<code> 4: Object beanInstance;/<code>
<code> 5: final BeanFactory parent = this;/<code>
<code> 6: if (System.getSecurityManager() != null) {/<code>
<code> 7: beanInstance = AccessController.doPrivileged(new PrivilegedAction<object>() {/<object>/<code>
<code> 8: public Object run() {/<code>
<code> 9: return getInstantiationStrategy().instantiate(mbd, beanName, parent);/<code>
<code> 10: }/<code>
<code> 11: }, getAccessControlContext());/<code>
<code> 12: }/<code>
<code> 13: else {/<code>
<code> 14: beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);/<code>
<code> 15: }/<code>
<code> 16: BeanWrapper bw = new BeanWrapperImpl(beanInstance);/<code>
<code> 17: initBeanWrapper(bw);/<code>
<code> 18: return bw;/<code>
<code> 19: }/<code>
<code> 20: catch (Throwable ex) {/<code>
<code> 21: throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);/<code>
<code> 22: }/<code>
<code> 23: }/<code>
這裡用cglib對bean進行實例化,cglib是一個常用的字節碼生成器的類庫,它提供了一系列的API來提供java字節碼生成和轉換的功能,如果有興趣可以查看cglib的使用文檔。另外生成bean的策略還有很多種,這裡只是選了最常用的方法來介紹。至此,bean實例創建過程就算完成了,然後通過populateBean方法將創建好的實例的依賴關係設置好,最終完成依賴注入的過程,由於篇幅關係這裡就不詳細列舉了,populateBean方法可以在AbstractAutowireCapableBeanFactory中找到。
小結
自己對Spring IOC代碼的學習暫時就到這裡,要搞懂一個特性,確實需要花費很大的功夫,Spring代碼量比較大,而且各個特性之間又有交叉,要梳理清楚不是件容易的事,不過回頭來看自己還是有收穫的,希望對看它的朋友也有一點收穫。
注意注意:以上分享的這些Spring筆記:面試錦集解析+學習筆記+學習導圖+Spring源碼視頻,如果你想要一起學習轉發後關注我私信【資料】免費領取吧
閱讀更多 路人甲java 的文章