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模塊提供 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的實例。
模塊提供了框架的基本組成部分,包括 IoC 和依賴注入功能,其中主要提供了三種注入方式,按bean的名稱、構造函數、類型來自動裝載,主要實現思路是,查找依賴,從Spring容器中取依賴的類,返回依賴類的實例,並轉換類型後,經過反射注入到目標bean的實例中。
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的幾個基本術語:
名稱 | 描述 |
---|---|
Aspect(切面) | 一個模塊具備一組提供橫切需求的 APIs。例如,一個日誌模塊爲了記錄日誌將被 AOP 方面調用。應用程序能夠擁有任意數量的方面,這取決於需求。 |
Join point(鏈接點) | 程序執行過程當中明確的點,如方法的調用或特定的異常被拋出。 |
Advice(通知點) | 特定的鏈接點,AOP框架執行的動做。各類類型的通知包括「around」、「before」、「after」和「throws」通知。 |
Pointcut(切點) | 這是一組一個或多個鏈接點,通知應該被執行 |
Introduction(引入) | 引用容許你添加新方法或屬性到現有的類中 |
Target object(目標對象) | 被一個或者多個方面所通知的對象,這個對象永遠是一個被代理對,也稱爲被通知對象 |
Weaving(織入點) | Weaving 把方面鏈接到其它的應用程序類型或者對象上,並建立一個被通知的對象。這些能夠在編譯時,類加載時和運行時完成 |
Spring 方面可使用下面提到的五種通知工做:
通知 | 描述 |
---|---|
前置通知(@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框架的全部理解,可能不是特別全面,若有不正之處,歡迎指出,謝謝!