Spring系列之AOP的理解和分析
今天是五一收假以來(lái)的第一天,距離下一周一共還有四天,這周主要是對(duì)Spring的重學(xué)習(xí)。這四天內(nèi)我將從以下幾個(gè)角度進(jìn)行分析和理解。
(1)AOP的理解和分析
(2)IOC的理解和分析
(3)對(duì)bean的理解和分析
(4)spring配置文件的理解和分析
首先今天對(duì)AOP的理解和分析,對(duì)aop的理解也分開闡述,對(duì)一個(gè)技術(shù)的思考,基本上都是從上學(xué)時(shí)候課本闡述一個(gè)新知識(shí)的順序進(jìn)行的。第一:什么是AOP?
第二:為什么要引入AOP?或者是AOP解決了什么問(wèn)題?
第三:如何簡(jiǎn)單的實(shí)現(xiàn)AOP?
第四:AOP對(duì)我們寫代碼時(shí)候的思考和幫助是什么?
現(xiàn)在,開始對(duì)AOP進(jìn)行闡述,
1 什么是AOP?
1.1 概念介紹
Spring的使命是簡(jiǎn)化Java代碼開發(fā),aop作為Spring的一個(gè)子模塊,也不例外。
AOP 是 Aspect Oriented Programming(面向切面編程) 的簡(jiǎn)稱,和OOP(面向?qū)ο缶幊?一樣是一種編程思想,是對(duì)OOP的一種補(bǔ)充。
如何理解什么是AOP呢?以日志為例,在很多管理系統(tǒng),比如訂單系統(tǒng)、推送系統(tǒng)等等都需要把日志記錄下來(lái)。如果每個(gè)業(yè)務(wù)邏輯里面都寫日志的相關(guān)代碼,那就重復(fù)太多了。
干脆把日志的相關(guān)邏輯代碼,統(tǒng)一封裝起來(lái)。然后在需要的地方嵌入即可。AOP也主要就是做嵌入這件事的。看下面這張圖。
新增訂單編輯訂單取消訂單推送訂單日志事務(wù)
AOP旨在將橫切關(guān)注點(diǎn)(crosscutting concern)從業(yè)務(wù)主體邏輯中進(jìn)行剝離,實(shí)現(xiàn)關(guān)注點(diǎn)分離,以提高程序的模塊化程度(及業(yè)務(wù)模塊只需關(guān)注業(yè)務(wù)邏輯,無(wú)需關(guān)注日志、安全、事務(wù)等通用邏輯)
上面提到了一些名詞,比如說(shuō),切面、關(guān)注點(diǎn)、橫切等,下面對(duì)這些名詞進(jìn)行解釋。
1.2 名詞解釋
AOP有自己的一套術(shù)語(yǔ),我們必須了解一下這些行話,才能更好地理解AOP。為了方便大家理解,下面將用課代表收作業(yè)作為例子。
通知 (Advice)
定義了在收作業(yè)前后需要做的事。常見的通知類型有:before、after、after-returning、around等。
連接點(diǎn) (JoinPoint)
連接點(diǎn)指程序運(yùn)行時(shí)允許插入切面的一個(gè)點(diǎn),可以是一個(gè)函數(shù)、一個(gè)包路徑、一個(gè)類、或者拋出的異常。有點(diǎn)類似于可以收作業(yè)的時(shí)間點(diǎn)。
切點(diǎn)(PointCut)
切點(diǎn)用于定義切面的位置,也就是捕獲哪些連接點(diǎn)的調(diào)用然后執(zhí)行"通知"的操作(什么地點(diǎn))。
切面(Aspect)
切面是切點(diǎn)和通知的聚合,定義了在哪一個(gè)切點(diǎn)做什么通知。
目標(biāo)對(duì)象( Target )
指被切面織入的對(duì)象。
引入(Introduction)
引入允許我們向現(xiàn)有的類添加新方法或?qū)傩浴?/p>
織入(Weaving)
織入是把切面應(yīng)用到切點(diǎn)對(duì)應(yīng)的連接點(diǎn)的過(guò)程。切面在指定連接點(diǎn)被織入到目標(biāo)對(duì)象中。
具體關(guān)系使用圖形化表示是:
2 為什么要引入AOP?
上面是定義,引入AOP的原因肯定是可以解決目前開發(fā)中存在的某些痛點(diǎn):
(1)目前的開發(fā)當(dāng)中,相互之間都是模塊化開發(fā),使用AOP可以有效的實(shí)現(xiàn)模塊化的思路。
(2)將輔助邏輯(日志、安全、監(jiān)控等)從業(yè)務(wù)主體邏輯中進(jìn)行剝離,同步進(jìn)行開發(fā)。
AOP是一種思想,這種思想是把一些業(yè)務(wù)邏輯剝離開,然后按照主業(yè)務(wù)邏輯進(jìn)行組合,最后達(dá)到想要的功能邏輯。
3 如何簡(jiǎn)單的實(shí)現(xiàn)AOP?
3.1 AOP編程思路
本圖是一個(gè)簡(jiǎn)單的思路。
明確需求創(chuàng)建切面類定義切點(diǎn)定義通知思考:要在哪個(gè)方法的什么時(shí)候做什么事(方法前?方法后?還是around ?)即選擇哪個(gè)連接點(diǎn)進(jìn)行執(zhí)行通知在切點(diǎn)附近(before?after?) 做什么操作
下面定義一個(gè)日志的簡(jiǎn)單案例,實(shí)現(xiàn)AOP。使用的是原始的注解方式:
3.2 案例實(shí)現(xiàn)AOP
3.2.1 明確需求
在某個(gè)方法上加上@FddLog,就會(huì)在執(zhí)行這個(gè)方法的前后,自動(dòng)輸出相應(yīng)的信息。下面以把大象放進(jìn)冰箱為例子進(jìn)行演示:
3.2.2 基本接口和實(shí)現(xiàn)
- public interface ElephentToRe{
- public void toRe();
- }
實(shí)現(xiàn)類如下:
- public class ElephentToReImpl implements ElephentToRe{
- public void toRe() {
- System.out.println("把大象放冰箱");
- }
- }
3.2.3 定義切面和通知
- public class ElephentToReHelper{
- public void beforeElephentToRe(){
- System.out.println("把冰箱門打開");
- }
- public void afterElephentToRe(){
- System.out.println("把冰箱門關(guān)上");
- }
- }
配置就好了
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
- <!-- 定義通知內(nèi)容,也就是切入點(diǎn)執(zhí)行前后需要做的事情 -->
- <bean id="elephentToReHelper" class="com.fdd.bean.ElephentToReHelper"></bean>
- <!-- 定義被代理者 -->
- <bean id="elephentToReImpl" class="com.fdd.bean.ElephentToReImpl"></bean>
- <aop:config>
- <aop:aspect ref="elephentToReHelper">
- <aop:before method="beforeElephentToRe" pointcut="execution(* *.toRe(..))" />
- <aop:after method="afterElephentToRe" pointcut="execution(* *.toRe(..))" />
- </aop:aspect>
- </aop:config>
- </beans>
3.2.4 測(cè)試看效果
- public class Test {
- public static void main(String[] args){
- @SuppressWarnings("resource")
- ApplicationContext appCtx = new FileSystemXmlApplicationContext("application.xml");
- ElephentToRe elephentToReImpl = (ElephentToRe)appCtx.getBean("elephentToReImpl");
- elephentToReImpl.toRe();
- }
- }
上面的這種方法是通過(guò)純粹的POJO切面來(lái)完成的。實(shí)現(xiàn)方式也比較簡(jiǎn)單。
4 我對(duì)AOP思想的看法
任何新技術(shù)的出現(xiàn)都是為了解決目前開發(fā)中存在的某些痛點(diǎn)。對(duì)于aop來(lái)說(shuō),其主要是把一些功能代碼進(jìn)行抽象封裝,和主業(yè)務(wù)邏輯代碼進(jìn)行剝離。在需要的地方進(jìn)行織入即可。
我的看法是
(1)在平時(shí)開發(fā)代碼的時(shí)候,完全可以把一些常見的,常用的功能代碼進(jìn)行封裝,盡量做到動(dòng)態(tài)配置。不同的功能模塊只需要進(jìn)行織入即可。
(2)定義業(yè)務(wù)邏輯的模板,比如說(shuō)如果要解決某一個(gè)業(yè)務(wù)功能,如果頁(yè)面類似,可以按照基本的框架進(jìn)行組合,然后使用配置平臺(tái)進(jìn)行可控化配置即可。
本文轉(zhuǎn)載自微信公眾號(hào)「愚公要移山」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系愚公要移山公眾號(hào)。