Spring 框架的設計理念與設計模式分析(2)

下面再看看 Spring 是如何調用攔截器的,下面是這個過程的時序圖:


圖 20.Spring 調用攔截器
圖 20.Spring 調用攔截器 

以上所說的都是 Jdk 動態代理,Spring 還支持一種 CGLIB 類代理,感興趣自己看吧。

Spring 中設計模式分析

Spring 中使用的設計模式也很多,比如工廠模式、單例模式、模版模式等,在《 Webx 框架的系統架構與設計模式》、《 Tomcat 的系統架構與模式設計分析》已經有介紹,這裏就不贅述了。這裏主要介紹代理模式和策略模式。

代理模式

代理模式原理

代理模式就是給某一個對象創建一個代理對象,而由這個代理對象控制對原對象的引用,而創建這個代理對象就是可以在調用原對象是可以增加一些額外的操作。下面是代理模式的結構:


圖 21. 代理模式的結構
圖 21. 代理模式的結構 
  • Subject:抽象主題,它是代理對象的真實對象要實現的接口,當然這可以是多個接口組成。
  • ProxySubject:代理類除了實現抽象主題定義的接口外,還必須持有所代理對象的引用
  • RealSubject:被代理的類,是目標對象。

Spring 中如何實現代理模式

Spring Aop 中 Jdk 動態代理就是利用代理模式技術實現的。在 Spring 中除了實現被代理對象的接口外,還會有 org.springframework.aop.SpringProxy 和 org.springframework.aop.framework.Advised 兩個接口。Spring 中使用代理模式的結構圖如下:


圖 22. Spring 中使用代理模式的結構圖
圖 22. Spring 中使用代理模式的結構圖 

$Proxy 就是創建的代理對象,而 Subject 是抽象主題,代理對象是通過 InvocationHandler 來持有對目標對象的引用的。

Spring 中一個真實的代理對象結構如下:


清單 10 代理對象 $Proxy4
            public class $Proxy4 extends java.lang.reflect.Proxy implements
            org.springframework.aop.framework.PrototypeTargetTests$TestBean
            org.springframework.aop.SpringProxy
            org.springframework.aop.framework.Advised
            {
            java.lang.reflect.Method m16;
            java.lang.reflect.Method m9;
            java.lang.reflect.Method m25;
            java.lang.reflect.Method m5;
            java.lang.reflect.Method m2;
            java.lang.reflect.Method m23;
            java.lang.reflect.Method m18;
            java.lang.reflect.Method m26;
            java.lang.reflect.Method m6;
            java.lang.reflect.Method m28;
            java.lang.reflect.Method m14;
            java.lang.reflect.Method m12;
            java.lang.reflect.Method m27;
            java.lang.reflect.Method m11;
            java.lang.reflect.Method m22;
            java.lang.reflect.Method m3;
            java.lang.reflect.Method m8;
            java.lang.reflect.Method m4;
            java.lang.reflect.Method m19;
            java.lang.reflect.Method m7;
            java.lang.reflect.Method m15;
            java.lang.reflect.Method m20;
            java.lang.reflect.Method m10;
            java.lang.reflect.Method m1;
            java.lang.reflect.Method m17;
            java.lang.reflect.Method m21;
            java.lang.reflect.Method m0;
            java.lang.reflect.Method m13;
            java.lang.reflect.Method m24;
            int hashCode();
            int indexOf(org.springframework.aop.Advisor);
            int indexOf(org.aopalliance.aop.Advice);
            boolean equals(java.lang.Object);
            java.lang.String toString();
            void sayhello();
            void doSomething();
            void doSomething2();
            java.lang.Class getProxiedInterfaces();
            java.lang.Class getTargetClass();
            boolean isProxyTargetClass();
            org.springframework.aop.Advisor; getAdvisors();
            void addAdvisor(int, org.springframework.aop.Advisor)
            throws org.springframework.aop.framework.AopConfigException;
            void addAdvisor(org.springframework.aop.Advisor)
            throws org.springframework.aop.framework.AopConfigException;
            void setTargetSource(org.springframework.aop.TargetSource);
            org.springframework.aop.TargetSource getTargetSource();
            void setPreFiltered(boolean);
            boolean isPreFiltered();
            boolean isInterfaceProxied(java.lang.Class);
            boolean removeAdvisor(org.springframework.aop.Advisor);
            void removeAdvisor(int)throws org.springframework.aop.framework.AopConfigException;
            boolean replaceAdvisor(org.springframework.aop.Advisor,
            org.springframework.aop.Advisor)
            throws org.springframework.aop.framework.AopConfigException;
            void addAdvice(org.aopalliance.aop.Advice)
            throws org.springframework.aop.framework.AopConfigException;
            void addAdvice(int, org.aopalliance.aop.Advice)
            throws org.springframework.aop.framework.AopConfigException;
            boolean removeAdvice(org.aopalliance.aop.Advice);
            java.lang.String toProxyConfigString();
            boolean isFrozen();
            void setExposeProxy(boolean);
            boolean isExposeProxy();
            }
            

策略模式

策略模式原理

策略模式顧名思義就是做某事的策略,這在編程上通常是指完成某個操作可能有多種方法,這些方法各有千秋,可能有不同的適應的場合,然而這些操作方法都有可能用到。各一個操作方法都當作一個實現策略,使用者可能根據需要選擇合適的策略。

下面是策略模式的結構:


圖 23. 策略模式的結構
圖 23. 策略模式的結構 
  • Context:使用不同策略的環境,它可以根據自身的條件選擇不同的策略實現類來完成所要的操作。它持有一個策略實例的引用。創建具體策略對象的方法也可以由他完成。
  • Strategy:抽象策略,定義每個策略都要實現的策略方法
  • ConcreteStrategy:具體策略實現類,實現抽象策略中定義的策略方法

Spring 中策略模式的實現

Spring 中策略模式使用有多個地方,如 Bean 定義對象的創建以及代理對象的創建等。這裏主要看一下代理對象創建的策略模式的實現。

前面已經瞭解 Spring 的代理方式有兩個 Jdk 動態代理和 CGLIB 代理。這兩個代理方式的使用正是使用了策略模式。它的結構圖如下所示:


圖 24. Spring 中策略模式結構圖
圖 24. Spring 中策略模式結構圖 

在上面結構圖中與標準的策略模式結構稍微有點不同,這裏抽象策略是 AopProxy 接口,Cglib2AopProxy 和 JdkDynamicAopProxy 分別代表兩種策略的實現方式,ProxyFactoryBean 就是代表 Context 角色,它根據條件選擇使用 Jdk 代理方式還是 CGLIB 方式,而另外三個類主要是來負責創建具體策略對象,ProxyFactoryBean 是通過依賴的方法來關聯具體策略對象的,它是通過調用策略對象的 getProxy(ClassLoader classLoader) 方法來完成操作。

總結

本文通過從 Spring 的幾個核心組件入手,試圖找出構建 Spring 框架的骨骼架構,進而分析 Spring 在設計的一些設計理念,是否從中找出一些好的設計思想,對我們以後程序設計能提供一些思路。接着再詳細分析了 Spring 中是如何實現這些理念的,以及在設計模式上是如何使用的。

通過分析 Spring 給我一個很大的啓示就是其這套設計理念其實對我們有很強的借鑑意義,它通過抽象複雜多變的對象,進一步做規範,然後根據它定義的這套規範設計出一個容器,容器中構建它們的複雜關係,其實現在有很多情況都可以用這種類似的處理方法。

雖然我很想把我對 Spring 的想法完全闡述清楚,但是所謂“書不盡言,言不盡意。”,有什麼不對或者不清楚的地方大家還是看看其源碼吧。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章