1. 程式人生 > >Spring 框架的設計理念與設計模式

Spring 框架的設計理念與設計模式

Spring 框架的設計理念與設計模式

Spring核心學習點

  • IoC容器:Spring核心是IoC容器,所以一定要透徹理解什麼是IoC容器,以及如何配置及使用容器,其他所有技術都是基於容器實現的;
  • 面向切面程式設計:首先還是明確概念,基本配置,最後是實現原理,接下來就是資料庫事務管理,其實Spring管理事務是通過面向切面程式設計實現的

一、Spring核心容器元件

Spring 的三大元件 :Bean 、 Context、Core
spring

Bean(一場演出中的演員):

提供了框架的基礎部分,包括反轉控制和依賴注入。其中Bean Factory是容器核心,本質是“工廠設計模式”的實現,而且無需程式設計實現“單例設計模式”,單例完全由容器控制,而且提倡面向介面程式設計,而非面向實現程式設計;所有應用程式物件及物件間關係由框架管理,從而真正把你從程式邏輯中把維護物件之間的依賴關係提取出來,所有這些依賴關係都由BeanFactory來維護

Context(演出的舞臺背景):

以Core和Beans為基礎,整合Beans模組功能並新增資源繫結、資料驗證、國際化、Java EE支援、容器生命週期、事件傳播等;核心介面是ApplicationContext,
ApplicationContext將完成:

  • (1)標識一個應用環境
  • (2)利用BeanFactory建立Bean物件
  • (3)儲存物件關係表
  • (4)能夠捕獲各種事件

Core(演出的道具):

封裝了框架依賴的最底層部分,包括資源訪問、型別轉換及一些常用工具類

二、Spring核心理念:

  • 面向Bean程式設計:將物件間的依賴關係用配置檔案管理,在一個叫做IOC容器中管理,這個容器裡就是被Bean包裹的物件

IoC容器工作原理

IoC容器實際上是Context元件結合另外其他兩個元件共同構建了一個Bean的關係網。

(1)初始化

初始化的過程主要就是讀取XML資源,並解析,最終註冊到Bean Factory中
初始化的流程:
!init

然後會重新整理,將該新加入的Bean放入整個關係網中去:重新整理的入口就在AbstractApplicationContextrefresh方法裡:

public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            //為重新整理準備新的Context
            this.prepareRefresh();
            //重新整理所有BeanFactory子容器 
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();  //建立BeanFactory
            this.prepareBeanFactory(beanFactory);  //新增一些工具類

            try {
                //
                this.postProcessBeanFactory(beanFactory);
                //
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

這個方法就是構建IoC容器的整個流程,非常重要,主要包含著幾個步驟:

(1)構建BeanFactory,以便生產所需的“演員”
(2)註冊可能感興趣的事件
(3)建立Bean 例項物件
(4)觸發被監聽的事件

首先this.obtainFreshBeanFactory(); //建立BeanFactory中會執行解析和註冊bean的過程,通過parseBeanDefinitionElement將XML的元素解析為BeanDefinition,然後存在BeanDefinitionHolder中,然後再利用BeanDefinitionHolder將BeanDefinition註冊,實質就是把BeanDefinition的例項put進BeanFactory中.
註冊過程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition),也就是說註冊的實質就是以beanName為key,以beanDefinition為value,將其put到HashMap中。

其中,這三行程式碼對Spring 的功能擴充套件起到了關鍵作用:

this.postProcessBeanFactory(beanFactory); // -> 註冊實現了BeanPostProcessor介面的Bean

this.invokeBeanFactoryPostProcessors(beanFactory);// ->初始化和執行BeanFactoryPostProcessors beans

this.registerBeanPostProcessors(beanFactory);  // -> 初始化和執行BeanPostProcessors beans

invokeBeanFactoryPostProcessors方法主要是獲取實現BeanFactoryPostProcessors介面的子類,並且執行它的postProcessBeanFactory方法.

這兩個介面的作用:
BeanFactoryPostProcessor和BeanPostProcessor,這兩個介面,都是Spring初始化bean時對外暴露的擴充套件點。

  • BeanFactoryPostProcessor介面實現類可以在當前BeanFactory初始化後,bean例項化之前對BeanFactory做一些處理。BeanFactoryPostProcessor是針對於bean容器的,在呼叫它時,BeanFactory只加載了bean的定義,還沒有對它們進行例項化,所以我們可以通過對BeanFactory的處理來達到影響之後例項化bean的效果。
  • BeanPostProcessor 介面定義了一個你可以自己實現的回撥方法,來實現你自己的例項化邏輯、依賴解決邏輯等,如果你想要在Spring完成物件例項化、配置、初始化之後實現自己的業務邏輯,你可以補充實現一個或多個BeanPostProcessor的實現。

如下圖所示:Spring Bean的生命週期:
!post

(2)依賴注入

當完成初始化IOC容器後,如果bean沒有設定lazy-init(延遲載入)屬性,那麼bean的例項就會在初始化IOC完成之後,及時地進行初始化。初始化時會先建立例項,然後根據配置利用反射對例項進行進一步操作,具體流程如下所示:

!fac

AbstractAutowireCapableBeanFactory類中,進行建立bean和注入bean的屬性

三、Spring中的設計模式

Spring 中的單例模式

Spring 中的代理模式

Spring中的 AOP就是給予動態代理實現的。

Spring 中的工廠模式

Spring中在各種BeanFactory以及ApplicationContext建立中都用到了典型的工廠方法模式,BeanFactory的設計原理如圖所示。

!bean

來看看其中BeanFactory原始碼:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    boolean containsBean(String var1);

    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;

    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    String[] getAliases(String var1);
}

Bean包裡主要包括Bean的定義、建立和解析,也就是配置xml檔案,被解析後就被轉化為Bean,由Spring統一管理.

Spring 中的模版方法