1.工廠設計模式
Spring使用工廠模式可以通過BeanFactory或ApplicationContext創建bean對象。
二者對比:
BeanFactory :延遲注入(使用到某個 bean 的時候纔會注入),相比於BeanFactory來說會佔用更少的內存,程序啓動速度更快。
ApplicationContext :容器啓動的時候,不管你用沒用到,一次性創建所有 bean 。BeanFactory 僅提供了最基本的依賴注入支持,ApplicationContext 擴展了 BeanFactory ,除了有BeanFactory的功能還有額外更多功能,所以一般開發人員使用ApplicationContext會更多。
2. 單例設計模式
Spring中bean的默認作用域就是singleton。
Spring實現單例的方式:
xml格式:<bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>
註解:@Scope(value = "singleton")
3.動態代理模式
Spring 實現 Aop 使用了動態代理模式。
先看看 Spring 如何實現代理類的,要實現代理類在 Spring 的配置文件中通常是這樣定一個 Bean 的,如下:
配置代理類 Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
配置上看到要設置被代理的接口,和接口的實現類也就是目標類,以及攔截器也就在執行目標方法之前被調用,這裏 Spring 中定義的各種各樣的攔截器,可以選擇使用。
下面看看 Spring 如何完成了代理以及是如何調用攔截器的。
前面提到 Spring Aop 也是實現其自身的擴展點來完成這個特性的,從這個代理類可以看出它正是繼承了 FactoryBean 的 ProxyFactoryBean,FactoryBean 之所以特別就在於它可以讓你自定義對象的創建方法。當然代理對象要通過 Proxy 類來動態生成。
下面是 Spring 創建的代理對象的時序圖:
Spring 創建了代理對象後,當你調用目標對象上的方法時,將都會被代理到 InvocationHandler 類的 invoke 方法中執行,這在前面已經解釋。在這裏 JdkDynamicAopProxy 類實現了 InvocationHandler 接口。
下面再看看 Spring 是如何調用攔截器的,下面是這個過程的時序圖:
以上所說的都是 Jdk 動態代理,Spring 還支持一種 CGLIB 類代理,這裏不討論。
4. 適配器模式
實現方式:SpringMVC中的適配器HandlerAdatper。
實現原理:HandlerAdatper根據Handler規則執行不同的Handler。
實現過程:
DispatcherServlet根據HandlerMapping返回的handler,向HandlerAdatper發起請求,處理Handler。HandlerAdapter根據規則找到對應的Handler並讓其執行,執行完畢後Handler會向HandlerAdapter返回一個ModelAndView,最後由HandlerAdapter向DispatchServelet返回一個ModelAndView。
實現意義:
HandlerAdatper使得Handler的擴展變得容易,只需要增加一個新的Handler和一個對應的HandlerAdapter即可。因此Spring定義了一個適配接口,使得每一種Controller有一種對應的適配器實現類,讓適配器代替controller執行相應的方法。這樣在擴展Controller時,只需要增加一個適配器類就完成了SpringMVC的擴展了。
5. 策略模式
Spring 中策略模式使用有多個地方,如 Bean 定義對象的創建以及代理對象的創建等。這裏主要看一下代理對象創建的策略模式的實現。
前面已經瞭解 Spring 的代理方式有兩個 Jdk 動態代理和 CGLIB 代理。這兩個代理方式的使用正是使用了策略模式。它的結構圖如下所示:
Spring 中策略模式結構圖
在上面結構圖中與標準的策略模式結構稍微有點不同,這裏抽象策略是 AopProxy 接口,Cglib2AopProxy 和 JdkDynamicAopProxy 分別代表兩種策略的實現方式,ProxyFactoryBean 就是代表 Context 角色,它根據條件選擇使用 Jdk 代理方式還是 CGLIB 方式。
config.isOptimize()和config.isProxyTargetClass()都默認false,然後判斷targetClass是否爲接口。
如果目標對象實現了接口,默認採用JDK動態代理;如果目標對象沒有實現接口,則採用Cglib動態代理。
https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html
https://blog.csdn.net/caoxiaohong1005/article/details/80039656