Spring源碼解讀

Spring Framework源碼地址:https://github.com/spring-projects/spring-frameworkjava

從目錄結構能夠看出整個Spring框架都聽從模塊化設計的思路,總共分爲20多個模塊,以下圖所示:git

從上圖能夠看出:github

Spring主要分爲五個部分:spring

一、測試模塊:主要實現了Spring的Junit等測試框架。編程

二、Spring核心容器:裏面都是Spring框架實現的基礎,主要包括了spring-beans、spring-core、spring-context等三個核心基礎模塊。緩存

三、Spring Data模塊:主要實現了包括Spring支持各類ORM框架,如JDBC Template、JPA、mybatis等的集成;還包括了Spring集成Marshalling XML的處理模塊;以及對Spring包括聲明式與編程式事務的支持。安全

四、Spring核心功能擴展模塊:主要在Spring核心模塊的基礎上,實現了包括AOP、對象綁定、i18n、類型轉換、事件、消息等框架機制的支持。mybatis

五、Spring Web模塊:主要實現了Spring對Web的支持,如SpringMvc、Webservice等的支持。app

 

從上面的分析能夠看出,Spring容器的全部實現都基於Spring核心模塊的實現,因此下文我主要基於Spring核心模塊的核心代碼實現作分析:框架

  • spring-beans模塊:

 spring-beans模塊提供 BeanFactory,工廠模式的微妙實現,它移除了編碼式單例的須要,而且能夠把配置和依賴從實際編碼邏輯中解耦。

下圖是BeanFactory的層次結構以下:

從上圖能夠看出:BeanFactory爲頂層的工廠接口,定義了獲取單個Bean實例特徵的方法,其下有Spring對於Jndi類型的Bean工廠的直接實現;AutowireCapableBeanFactory 定義了自動裝載Bean一系列接口,爲Spring容器實現自動裝載功能提供支持;HierarchicalBeanFactory爲BeanFactory提供層級關係,一個應用中能夠存在多個BeanFactory,該類即爲多個BeanFactory提供了層級關係,定義了獲取父BeanFactory與當前層次BeanFactory是否包含某個Bean實例的方法;ListableBeanFactory定義了獲取Spring容器中全部某類(所有)Bean實例的方法。

AutowireCapableBeanFactory層次結構圖以下:

AbstractAutowireCapableBeanFactory提供了可自動裝配的Bean Factory的默認實現;DefaultListableBeanFactory爲可自動裝載的ConfigurableListableBeanFactory實現,該BeanFactory既知足可列出全部Bean的同時,又能夠實現自動裝配;XmlBeanFactory爲Spring容器提供的從xml文件中讀取BeanDefinition爲DefaultListableBeanFactory的一種實現,目前在Spring Framework的最新版本中已不推薦使用。其中HierarchicalBeanFactory和ListableBeanFactory的實現關係與AutowireCapableBeanFactory相相似,最終,DefaultListableBeanFactory同時實現了三種類型的BeanFactory的接口。因此,下文主要以DefaultListableBeanFactory爲例作Spring BeanFactory的實現分析:

從上圖能夠看出:DefaultListableBeanFactory中以線程安全ConcurrentHashMap容器存儲了Spring容器中全部Bean的定義與beanName的鍵值對與緩存了單例的Bean實例,以此來實現知足三種條件的BeanFactory;Spring獲取Bean實例時首先會從緩存中去取bean實例,若是取不到,則建立實例,下面主要分析BeanFactory建立Bean實例的方法:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {//初始化bean
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {//初始化實例,爲成員變量注入值
			populateBean(beanName, mbd, instanceWrapper);
            //執行初始化方法及生成實例後方法,如按照順序執行ApplicationContextAware的setApplicationContext方法、BeanPostProcessor的postProcessBeforeInitialization方法、InitializingBean的afterPropertiesSet方法、BeanPostProcessor的postProcessAfterInitialization等
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

從上面個方法能夠基本看出Spring容器獲取Bean的步驟,先經過bean的名稱查找緩存是否存在該實例,若是存在,則直接返回,不存在,則建立實例,建立bean實例的過程爲,先從beanDefinition的map中取出BeanDefinnition,生成一個實例或cglib代理,注入依賴成員變量,執行初始化等方法,放入緩存,最終運行類型轉換,返回給調用者一個bean的實例。

  • spring-core模塊:

模塊提供了框架的基本組成部分,包括 IoC 和依賴注入功能,其中主要提供了三種注入方式,按bean的名稱、構造函數、類型來自動裝載,主要實現思路是,查找依賴,從Spring容器中取依賴的類,返回依賴類的實例,並轉換類型後,經過反射注入到目標bean的實例中。

  • spring-context模塊:

context模塊創建在由core和 beans 模塊的基礎上創建起來的,它以一種相似於JNDI註冊的方式訪問對象。Context模塊繼承自Bean模塊,而且添加了國際化(好比,使用資源束)、事件傳播、資源加載和透明地建立上下文(好比,經過Servelet容器)等功能。Context模塊也支持Java EE的功能,好比EJB、JMX和遠程調用等。ApplicationContext接口是Context模塊的焦點。spring-context-support提供了對第三方庫集成到Spring上下文的支持,好比緩存(EhCache, Guava, JCache)、郵件(JavaMail)、調度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。

咱們平時使用獲取Bean實例每每不會直接經過BeanFactory獲取,是經過ApplicationContext來進行獲取的。

從上圖能夠看出,Spring ApplicationContext總共提供了三種基礎類型的實現ClassPathXmlApplicationContext(從classpath下spring配置文件,最經常使用)、FileSystemXmlApplicationContext(從文件系統中讀取spring配置文件)、AnnotationConfigReactiveWebApplicationContext(基於註解配置讀入)來生成對應的ApplicationContext;這也是整個Spring容器的初始化入口。

下面方法是Spring容器的初始化方法:

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

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

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

從上面代碼能夠看出,Spring初始化容器的過程爲:

一、加載配置文件(xml或註解類)

二、prepareRefresh方法加載上下文環境的Properties和準備Spring的上下文環境

三、obtainFreshBeanFactory生成BeanFactory

四、prepareBeanFactory爲上一步生成的BeanFactory設置ClassLoader、callbacks(回調上下文)、ApplicationContextAwareProcessor(Spring生成Bean的初始化處理類)、依賴類、環境變量等信息

五、postProcessBeanFactory某些子類實現對BeaFactory的初始化後置邏輯處理

六、invokeBeanFactoryPostProcessors執行第4步設置的BeanFactoryPostProcessor對BeanFactory的初始化後置邏輯處理、BeanDefinitionRegistryPostProcessor實現向BeanFactory執行加入RootBeanDefinition等操做

七、registerBeanPostProcessors方法在BeanFactory註冊Bean生成的BeanPostProcessor(攔截Bean的建立)

八、initMessageSource方法爲Spring上下文初始化MessageSource

九、initApplicationEventMulticaster方法爲Spring的Context設置ApplicationEventMulticaster,提供BeanFactory管理ApplicationListener個數及廣播事件的類

十、onRefresh方法爲Spring上下文註冊一些特殊的Bean

十一、registerListeners方法在Spring容器中註冊全部的ApplicationListener

十二、finishBeanFactoryInitialization初始化全部的非懶加載的Bean,註冊到Spring容器中

1三、finishRefresh方法完成Spring容器的初始化操做,清空一些資源、發佈Spring上下文的ContextRefreshedEvent事件

1四、resetCommonCaches方法清空一些初始化緩存

通過上面的步驟分析,咱們能夠對Spring容器的核心實現有一個深刻的瞭解。

  • spring-aop模塊:

首先,咱們須要知道Spring的AOP的幾個基本術語:

Spring AOP基本術語
名稱 描述
Aspect(切面) 一個模塊具備一組提供橫切需求的 APIs。例如,一個日誌模塊爲了記錄日誌將被 AOP 方面調用。應用程序能夠擁有任意數量的方面,這取決於需求。
Join point(鏈接點) 程序執行過程當中明確的點,如方法的調用或特定的異常被拋出。
Advice(通知點) 特定的鏈接點,AOP框架執行的動做。各類類型的通知包括「around」、「before」、「after」和「throws」通知。
Pointcut(切點) 這是一組一個或多個鏈接點,通知應該被執行
Introduction(引入) 引用容許你添加新方法或屬性到現有的類中
Target object(目標對象) 被一個或者多個方面所通知的對象,這個對象永遠是一個被代理對,也稱爲被通知對象
Weaving(織入點) Weaving 把方面鏈接到其它的應用程序類型或者對象上,並建立一個被通知的對象。這些能夠在編譯時,類加載時和運行時完成

 

Spring 方面可使用下面提到的五種通知工做:

Spring的5種通知類型
通知 描述
前置通知(@Before) 在一個方法執行以前,執行通知
後置通知(@After) 在一個方法執行以後,不考慮其結果,執行通知
返回後通知(@AfterReturning) 在一個方法執行以後,只有在方法成功完成時,才能執行通知
拋出異常後通知(@AfterThrowing) 在一個方法拋出異常後執行
環繞通知(@Around) 在一個方法執行先後通知

 下面是Spring AOP的切點聲明接口:

public interface Pointcut {

	/**
	 * Return the ClassFilter for this pointcut.
	 * @return the ClassFilter (never {@code null})
	 */
	ClassFilter getClassFilter();

	/**
	 * Return the MethodMatcher for this pointcut.
	 * @return the MethodMatcher (never {@code null})
	 */
	MethodMatcher getMethodMatcher();


	/**
	 * Canonical Pointcut instance that always matches.
	 */
	Pointcut TRUE = TruePointcut.INSTANCE;

}

從上面能夠看出Spring的切點其實是一個定義了切點方法及類描述的描述實現類。

那麼Spring容器是如何初始化實現AOP的功能呢,要實現AOP功能有兩種方式:

    一、靜態代理,生成的編譯類就已經實現AOP代理類

    二、動態代理,程序運行時動態地生成AOP代理類,Spring容器中使用JDK、Cglib等

從上面的Spring容器初始化分析中,能夠找到AbstractAutowireCapableBeanFactory類中

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

  初始化Bean時,會觸發Aware實現的方法,也會觸發BeanPostProcessor實現的方法,其中在BeanPostProcessor的實現postProcessAfterInitialization方法中,完成初始化後,有一個AbstractAdvisingBeanPostProcessor的實現,這之中實現了Spring生成AOP的代理對象方法:

public Object postProcessAfterInitialization(Object bean, String beanName) {
		if (bean instanceof AopInfrastructureBean || this.advisor == null) {
			// Ignore AOP infrastructure such as scoped proxies.
			return bean;
		}

		if (bean instanceof Advised) {
			Advised advised = (Advised) bean;
			if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
				// Add our local Advisor to the existing proxy's Advisor chain...
				if (this.beforeExistingAdvisors) {
					advised.addAdvisor(0, this.advisor);
				}
				else {
					advised.addAdvisor(this.advisor);
				}
				return bean;
			}
		}

		if (isEligible(bean, beanName)) {
			ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
			if (!proxyFactory.isProxyTargetClass()) {
				evaluateProxyInterfaces(bean.getClass(), proxyFactory);
			}
			proxyFactory.addAdvisor(this.advisor);
			customizeProxyFactory(proxyFactory);
			return proxyFactory.getProxy(getProxyClassLoader());
		}

		// No async proxy needed.
		return bean;
	}
@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

從上圖能夠看出Spring實現AOP代理類的獲取時,有兩種實現,第一種基於Cglib的代理,第二種基於Jdk的動態代理,Spring優先採用Jdk的動態代理實現。

 

以上就是我對Spring框架的全部理解,可能不是特別全面,若有不正之處,歡迎指出,謝謝!