1. 程式人生 > 實用技巧 >Spring,IOC原始碼分析

Spring,IOC原始碼分析

有錯勿噴

1.首先是Spring,IOC的基本概念

  • IOC是一個容器
  • 容器啟動的時候建立所有單例項物件
  • 我們可以直接從容器中獲取到這個物件

2.除錯流程

  • ioc容器的啟動過程?啟動期間都做了什麼(什麼時候建立所有單例項bean )
  • ioc是如何建立這些單例項bean ,並如何管理的;到底儲存在了那裡?

3.我們首先觀察物件是什麼時候建立的

  1. 我們可以先寫一個實體類Person,並且寫一個無參及有參構造器,並寫上輸出語句,這樣我們就可以在建立Person物件的時候觀察到
public class Person {
    private String name;
    public Person() {
        System.out.println("person構造");
    }
    getset方法。。。
    toString方法。。。
  1. 在容器中配置,建立一個Spring的配置檔案
<bean id="person01" class="com.xj.bean.Person">
    <property name="name" value="xj"></property>
</bean>

4.接下來就可以開始我們的除錯啦

1. 首先對於Spring,使用以下程式碼建立物件

ApplicationContext ioc = new ClassPathXMLApplicationContext("ioc.xml");

2. 進入建立ioc容器物件

ClassPathXMLApplicationContext.java中,呼叫另一個構造器

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}

3. 在這個裡當我們執行完refresh()方法後,可以觀察到控制檯列印了Person的構造器,我們可以知道,元件的建立在refresh中,所以我們進入refresh中

refresh();

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
			throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
          refresh();
    }
}

4. finishBeanFactoryInitialization(beanFactory);

AbstractApplicationContext.java中,我們可以觀察到在
finishBeanFactoryInitialization(beanFactory);之後會列印,我們再進入

        public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {

			prepareRefresh();
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			prepareBeanFactory(beanFactory);
			try {
				postProcessBeanFactory(beanFactory);
				invokeBeanFactoryPostProcessors(beanFactory);
				registerBeanPostProcessors(beanFactory);
				initMessageSource();
				initApplicationEventMulticaster();
				onRefresh();
				registerListeners();

                              //在這裡列印---
				**finishBeanFactoryInitialization(beanFactory);**

				finishRefresh();
			}
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			}
			finally {
				resetCommonCaches();
			}
		}
	}

5. beanFactory.preInstantiateSingletons();

AbstractApplicationContext.java中,我們可以再次觀察到最後一句的時候列印
beanFactory.preInstantiateSingletons();,所以我們再進去

        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
				@Override
				public String resolveStringValue(String strVal) {
					return getEnvironment().resolvePlaceholders(strVal);
				}
			});
		}
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}
		beanFactory.setTempClassLoader(null);
		beanFactory.freezeConfiguration();
                //這裡進入
		beanFactory.preInstantiateSingletons();
	}

6. preInstantiateSingletons();

這裡就是我們重頭戲的開始了

        @Override
	public void preInstantiateSingletons() throws BeansException {
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Pre-instantiating singletons in " + this);
		}
                //拿到所有要建立的bean的名字,也就是我們配置的bean的id,如上面我配置的<bean id="person01" class="com.xj.bean.Person">,也就是這個person01
                //如果有多個的話,就person01,person02,person03
		List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
                  
                //按照順序建立bean
		for (String beanName : beanNames) {
                        //根據bean id 獲取到bean的定義資訊,如全類名,是否單例項,是否懶載入等等
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                        //判斷bean是單例項,並且不是抽象,不是懶載入
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                                //是否是實現了FactoryBean介面的bean,我們的person不是,所以看下面的else
				if (isFactoryBean(beanName)) {
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean<?>) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
                                //否則的話,執行getBean,我們進入getBean
				else {
					getBean(beanName);
				}
			}
		}
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(new PrivilegedAction<Object>() {
						@Override
						public Object run() {
							smartSingleton.afterSingletonsInstantiated();
							return null;
						}
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

7. getBean();

AbstractBeanFactory.java中
getBean方法內部呼叫doGetBean()方法,我們再次進入

        @Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

8. doGetBean(name, null, null, false);

        @SuppressWarnings("unchecked")
	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;

		//先從已經註冊的所有單例項bean中看有沒有這個bean,第一次建立肯定是沒有的,所以執行下面的else
		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 {
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				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);
                                //拿到建立當前bean之前需要提前建立(依賴)的bean,dependsOn,如果有就迴圈建立
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
                                                //這邊再次呼叫getBean建立
						getBean(dep);
					}
				}
                                //這裡就是真正的建立bean例項
				if (mbd.isSingleton()) {
                                        //呼叫getSingleton建立bean,見9
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								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()) {
					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;
			}
		}

		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;
	}

9. getSingleton(beanName, new ObjectFactory() {...
        public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
		synchronized (this.singletonObjects) {
                        //先從一個地方將bean get出來
                        //這個singletonObjects就是一個map,裡面儲存所有的單例項物件,也就是我們的容器
                        //如果容器中有的話,就不會建立
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<Exception>();
				}
				try {
                                        //bean建立,利用反射建立物件
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
                                        //將剛建立好的bean新增到singletonObjects中
					addSingleton(beanName, singletonObject);
				}
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	}

10. ioc實質

我們剛才已經看到了一個ioc容器
singletonObjects:
快取所有單例項的物件,物件名->物件例項
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

IOC容器之一:儲存單例項bean的地方;
IOC就是眾多map的集合