體系架構圖講解知識點
“spring源碼,看過嗎?“當朋友跟我說起來面試的時候問到的這個問題,我表面波瀾不驚,內心實則一萬隻神獸奔騰而過,面試都已經這樣的了嗎?
突然感覺好難啊,平時應付工作就已經精疲力竭了,哪裏來的功夫去做別的啊,我個人覺得應該大多數的程序員可能跟我一樣的狀態,那該怎麼辦,那就把有限的精力花在刀刃上吧,爲此,我整理了關於sping、ioc、aop的相關知識,形成了一套腦圖供大家學習使用,有體系的學習總好過漫無目的的瞎撞吧
關於Spring
Spring是一個開源框架,是爲了解決企業應用程序開發複雜性而創建的。框架的主要優勢之一就是其分層架構,分層架構允許您選擇使用哪一個組件,同時爲 J2EE 應用程序開發提供集成的框架。
它是一個全面的、企業應用開發一站式的解決方案,貫穿表現層、業務層、持久層。但是Spring仍然可以和其他的框架無縫整合。
Sping架構
Spring框架是分模塊存在,除了最核心的Spring Core Container(即Spring容器)是必要模塊之外,其他模塊都是可選,視需要而定。大約有20多個模塊。
Spring3與Spring4是有區別的,4.0主要是對Java 8的新函數式語法進行支持,還有加強了對網絡各種新技術比如http-streaming, websocket的更好的支持。
一般來說,Spring主要分爲7個模塊:
Spring的主要jar包
常用註解
bean注入與裝配的的方式有很多種,可以通過xml,getset方式,構造函數或者註解等。簡單易用的方式就是使用Spring的註解了,Spring提供了大量的註解方式,讓項目閱讀和開發起來更加方便。
第三方框架集成
Spring框架的開發不是爲了替代現有的優秀第三方框架,而是通過集成的方式把它們都連接起來。下面總結了一些常集成的優秀框架。
spring ioc
寫過java的都知道:所有的對象都必須創建;或者說:使用對象之前必須先創建。而使用ioc之後,你就可以不再手動創建對象,而是從ioc容器中直接獲取對象。
就好像我們無需考慮對象的銷燬回收一樣,因爲java垃圾回收機制幫助我們實現了這個過程;而ioc則是讓我們無需考慮對象的創建過程,由ioc容器幫我們實現對象的創建、注入等過程。
控制反轉
spring ioc容器
在Spring框架中的核心組件只有三個:Core、Context和Bean。它們構建起了整個Spring的骨骼架構,沒有它們就不可能有AOP、Web等特性功能。
如果說在三個核心中再選出一個核心,那就非Bean莫屬了。可以說,Spring就是面向Bean的編程,Bean在Spring中才是真正的主角。
Spring爲何如此流行?你會發現Spring解決了一個非常關鍵的問題,它可以讓你對對象之間的關係轉而用配置文件來管理,或者註解,也就是它的依賴注入機制。而這個注入關係在一個叫Ioc的容器中管理。Ioc容器就是被Bean包裹的對象。Spring正是通過把對象包裝在Bean中從而達到管理這些對象及做一些列額外操作的目的。
核心組件協同工作
BeanFactory與ApplacationContext的區別
IOC中最核心的接口是Beanfactory提供IOC的高級服務,而ApplicationContext是建立在BeanFactory基礎之上提供抽象的面向應用的服務。
3種注入方式
在Spring框架中,依賴注入(DI)的設計模式是用來定義對象彼此間的依賴。使用xml配置bean的情況下,它主要有兩種類型:
-
Setter方法注入
-
構造器注入
當然,有了註解之後,使用註解的方式更加方便快捷。即自動裝配功能實現屬性自動注入(@autowire)。
寫到這裏,讓我想起了最近在牛客網上看的一道選擇題了:
下面有關spring的依賴注入,說法錯誤的是?
A、依賴注入通常有如下兩種:設置注入和構造注入:
B、構造注入可以在構造器中決定依賴關係的注入順序,優先依賴的優先注入
C、當設值注入與構造注入同時存在時,先執行構造注入,再執行設值注入
D、設值注入是指IoC容器使用屬性的setter方法來注入被依賴的實例。這種注入方式比較簡單、直觀
牛客網給出的答案是選C,不過網友們好像對答案有不同的意見哈。查看網友評論及答案
原理解析
Spring的代碼還真是不好讀,分得太細了,文字也是難以描述出來,看了別人有關的博客,貼了好多代碼,畫了好多ER圖來描述關鍵接口或類之間的關係。這麼一篇這麼長文章下來,大家也未必會認真讀代碼,看ER圖,乾脆也不跟風了。就貼了一點在我看來特關鍵的代碼,嘿嘿。
######context的初始化過程
當運行 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); 構造方法ClassPathXmlApplicationContext(String configLocation)調用了this(new String[] {configLocation}, true, null);, 該構造方法具體代碼如下。
######從時序圖來看啓動上述初始化
springaop
AOP(Aspect-OrientedProgramming,面向方面編程),可以說是OOP(Object-Oriented Programing,面向對象編程)的補充和完善。OOP允許你定義從上到下的關係,但並不適合定義從左到右的關係。例如日誌功能。日誌代碼往往水平地散佈在所有對象層次中,而與它所散佈到的對象的核心功能毫無關係。這種散佈在各處的無關的代碼被稱爲橫切(cross-cutting)代碼,在OOP設計中,它導致了大量代碼的重複,而不利於各個模塊的重用。
而AOP技術則恰恰相反,它利用一種稱爲“橫切”的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,並將其名爲“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。
aop使用場景
aop框架種類
-
AspectJ
-
JBoss AOP
-
Spring AOP
使用aop可以做的事情有很多。
-
性能監控,在方法調用前後記錄調用時間,方法執行太長或超時報警。
-
緩存代理,緩存某方法的返回值,下次執行該方法時,直接從緩存裏獲取。
-
軟件破解,使用AOP修改軟件的驗證類的判斷邏輯。
-
記錄日誌,在方法執行前後記錄系統日誌。
-
工作流系統,工作流系統需要將業務代碼和流程引擎代碼混合在一起執行,那麼我們可以使用AOP將其分離,並動態掛接業務。
-
權限驗證,方法執行前驗證是否有權限執行當前方法,沒有則拋出沒有權限執行異常,由業務代碼捕捉。
觀察一下傳統編碼方式與使用aop的區別
核心概念
描述AOP常用的一些術語有通知(Adivce)、切點(Pointcut)、連接點(Join point)、切面(Aspect)、引入(Introduction)、織入(Weaving)、通知(Advice)等。
簡單例子
相比xml配置,基於註解的方式更加簡潔方便。
@Aspect
public class TransactionDemo {
@Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")
public void point(){
}
@Before(value="point()")
public void before(){
System.out.println("transaction begin");
}
@AfterReturning(value = "point()")
public void after(){
System.out.println("transaction commit");
}
@Around("point()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("transaction begin");
joinPoint.proceed();
System.out.println("transaction commit");
}
}
在applicationContext.xml中配置。
<aop:aspectj-autoproxy />
<bean id = "transactionDemo" class = "com.yangxin.core.transaction.TransactionDemo" />
spring aop原理
通過前面介紹可以知道:AOP 代理其實是由 AOP 框架動態生成的一個對象,該對象可作爲目標對象使用。AOP 代理包含了目標對象的全部方法,但 AOP 代理中的方法與目標對象的方法存在差異:AOP 方法在特定切入點添加了增強處理,並回調了目標對象的方法。
Spring 的 AOP 代理由 Spring 的 IoC 容器負責生成、管理,其依賴關係也由 IoC 容器負責管理。因此,AOP 代理可以直接使用容器中的其他 Bean 實例作爲目標,這種關係可由 IoC 容器的依賴注入提供。
aop開發時,其中需要程序員參與的只有 3 個部分:
-
定義普通業務組件。
-
定義切入點,一個切入點可能橫切多個業務組件。
-
定義增強處理,增強處理就是在 AOP 框架爲普通業務組件織入的處理動作。
爲了理清關係,先來個類關係圖。
兩種動態代理方式
Spring默認採取的動態代理機制實現AOP,當動態代理不可用時(代理類無接口)會使用CGlib機制。
Spring提供了兩種方式來生成代理對象: JDKProxy和Cglib,具體使用哪種方式生成由AopProxyFactory根據AdvisedSupport對象的配置來決定。默認的策略是如果目標類是接口,則使用JDK動態代理技術,否則使用Cglib來生成代理。
JDK動態代理
-
JDK動態代理主要涉及到java.lang.reflect包中的兩個類:Proxy和InvocationHandler。InvocationHandler是一個接口,通過實現該接口定義橫切邏輯,並通過反射機制調用目標類的代碼,動態將橫切邏輯和業務邏輯編制在一起。
-
Proxy利用InvocationHandler動態創建一個符合某一接口的實例,生成目標類的代理對象。
CGLib動態代理
-
CGLib全稱爲Code Generation Library,是一個強大的高性能,高質量的代碼生成類庫,可以在運行期擴展Java類與實現Java接口,CGLib封裝了asm,可以再運行期動態生成新的class。和JDK動態代理相比較:JDK創建代理有一個限制,就是隻能爲接口創建代理實例,而對於沒有通過接口定義業務方法的類,則可以通過CGLib創建動態代理。
知識拓展
通過上面的分析,大家是否有種熟悉的感覺,似乎和攔截器、過濾器的功能相似。那麼問題來了,aop與攔截器、過濾器是什麼關係。
先來回顧一下攔截器與過濾器。如下圖一網友的測試,在web.xml中註冊了TestFilter1和TestFilter2。然後在spring的配置文件中配置了BaseInterceptor和TestInterceptor。得到的結果如下圖所示。從圖中可以看出,攔截器和過濾器都橫切了業務方法,看似符合aop的思想。
Filter過濾器:攔截web訪問url地址。Interceptor攔截器:攔截以 .action結尾的url,攔截Action的訪問。Spring AOP攔截器:只能攔截Spring管理Bean的訪問(業務層Service)