AOP理論

1爬虱、概念

AOP(Aspect Oriented Programming)意為:面向切面編程,通過預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)蔽莱。AOP是OOP的延續(xù),是軟件開發(fā)中的一個(gè)熱點(diǎn)制轰,也是Spring框架中的一個(gè)重要內(nèi)容敦腔,是函數(shù)式編程的一種衍生范型均澳。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低符衔,提高程序的可重用性找前,同時(shí)提高了開發(fā)的效率。

2判族、Aop在Spring中的作用

提供聲明式事務(wù)躺盛;允許用戶自定義切面

以下名詞需要了解下:

  • 橫切關(guān)注點(diǎn):跨越應(yīng)用程序多個(gè)模塊的方法或功能。即是形帮,與我們業(yè)務(wù)邏輯無關(guān)的槽惫,但是我們需要關(guān)注的部分,就是橫切關(guān)注點(diǎn)辩撑。如日志 , 安全 , 緩存 , 事務(wù)等等 ....
  • 切面(ASPECT):橫切關(guān)注點(diǎn) 被模塊化 的特殊對(duì)象界斜。即,它是一個(gè)類合冀。
  • 通知(Advice):切面必須要完成的工作各薇。即,它是類中的一個(gè)方法君躺。
  • 目標(biāo)(Target):被通知對(duì)象峭判。
  • 代理(Proxy):向目標(biāo)對(duì)象應(yīng)用通知之后創(chuàng)建的對(duì)象。
  • 切入點(diǎn)(PointCut):切面通知 執(zhí)行的 “地點(diǎn)”的定義晰洒。
  • 連接點(diǎn)(JointPoint):與切入點(diǎn)匹配的執(zhí)行點(diǎn)朝抖。

SpringAOP中,通過Advice定義橫切邏輯谍珊,Spring中支持5種類型的Advice:

即 Aop 在 不改變?cè)写a的情況下 , 去增加新的功能 .

3治宣、使用Spring實(shí)現(xiàn)Aop

【重點(diǎn)】使用AOP織入急侥,需要導(dǎo)入一個(gè)依賴包!

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <version>1.9.4</version>
</dependency>

1侮邀、第一種方式

通過 Spring API 實(shí)現(xiàn)

首先編寫我們的業(yè)務(wù)接口和實(shí)現(xiàn)類

public interface UserService {

   public void add();

   public void delete();

   public void update();

   public void search();

}
public class UserServiceImpl implements UserService{

   @Override
   public void add() {
       System.out.println("增加用戶");
  }

   @Override
   public void delete() {
       System.out.println("刪除用戶");
  }

   @Override
   public void update() {
       System.out.println("更新用戶");
  }

   @Override
   public void search() {
       System.out.println("查詢用戶");
  }
}

然后去寫我們的增強(qiáng)類 , 我們編寫兩個(gè) , 一個(gè)前置增強(qiáng) 一個(gè)后置增強(qiáng)

public class Log implements MethodBeforeAdvice {

   //method : 要執(zhí)行的目標(biāo)對(duì)象的方法
   //objects : 被調(diào)用的方法的參數(shù)
   //Object : 目標(biāo)對(duì)象
   @Override
   public void before(Method method, Object[] objects, Object o) throws Throwable {
       System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被執(zhí)行了");
  }
}
public class AfterLog implements AfterReturningAdvice {
   //returnValue 返回值
   //method被調(diào)用的方法
   //args 被調(diào)用的方法的對(duì)象的參數(shù)
   //target 被調(diào)用的目標(biāo)對(duì)象
   @Override
   public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
       System.out.println("執(zhí)行了" + target.getClass().getName()
       +"的"+method.getName()+"方法,"
       +"返回值:"+returnValue);
  }
}

最后去spring的文件中注冊(cè) , 并實(shí)現(xiàn)aop切入實(shí)現(xiàn) , 注意導(dǎo)入約束 .

<?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.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注冊(cè)bean-->
    <bean id="userService" class="com.nie.service.UserServiceImpl"/>
    <bean id="log" class="com.nie.log.Log"/>
    <bean id="afterLog" class="com.nie.log.AfterLog"/>
<!--    配置aop-->
    <aop:config>
        <!--切入點(diǎn) expression:表達(dá)式匹配要執(zhí)行的方法-->
        <aop:pointcut id="pointcut" expression="execution(* com.nie.service.UserServiceImpl.*(..))"/>
        <!--執(zhí)行環(huán)繞; advice-ref執(zhí)行方法 . pointcut-ref切入點(diǎn)-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>

    </aop:config>



</beans>

測(cè)試

public class MyTest {
   @Test
   public void test(){
       ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
       UserService userService = (UserService) context.getBean("userService");
       userService.search();
  }
}

Aop的重要性 : 很重要 . 一定要理解其中的思路 , 主要是思想的理解這一塊 .

Spring的Aop就是將公共的業(yè)務(wù) (日志 , 安全等) 和領(lǐng)域業(yè)務(wù)結(jié)合起來 , 當(dāng)執(zhí)行領(lǐng)域業(yè)務(wù)時(shí) , 將會(huì)把公共業(yè)務(wù)加進(jìn)來 . 實(shí)現(xiàn)公共業(yè)務(wù)的重復(fù)利用 . 領(lǐng)域業(yè)務(wù)更純粹 , 程序猿專注領(lǐng)域業(yè)務(wù) , 其本質(zhì)還是動(dòng)態(tài)代理 .

2坏怪、第二種方式

自定義類來實(shí)現(xiàn)Aop

目標(biāo)業(yè)務(wù)類不變依舊是userServiceImpl

第一步 : 寫我們自己的一個(gè)切入類

public class DiyPointcut {

   public void before(){
       System.out.println("---------方法執(zhí)行前---------");
  }
   public void after(){
       System.out.println("---------方法執(zhí)行后---------");
  }
   
}

去spring中配置

<!--第二種方式自定義實(shí)現(xiàn)-->
<!--注冊(cè)bean-->
<bean id="diy" class="com.kuang.config.DiyPointcut"/>

<!--aop的配置-->
<aop:config>
   <!--第二種方式:使用AOP的標(biāo)簽實(shí)現(xiàn)-->
   <aop:aspect ref="diy">
       <aop:pointcut id="diyPonitcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
       <aop:before pointcut-ref="diyPonitcut" method="before"/>
       <aop:after pointcut-ref="diyPonitcut" method="after"/>
   </aop:aspect>
</aop:config>

測(cè)試:

public class MyTest {
   @Test
   public void test(){
       ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
       UserService userService = (UserService) context.getBean("userService");
       userService.add();
  }
}

3、第三種方式

使用注解實(shí)現(xiàn)

第一步:編寫一個(gè)注解實(shí)現(xiàn)的增強(qiáng)類

package com.kuang.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotationPointcut {
   @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
   public void before(){
       System.out.println("---------方法執(zhí)行前---------");
  }

   @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
   public void after(){
       System.out.println("---------方法執(zhí)行后---------");
  }

   @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
   public void around(ProceedingJoinPoint jp) throws Throwable {
       System.out.println("環(huán)繞前");
       System.out.println("簽名:"+jp.getSignature());
       //執(zhí)行目標(biāo)方法proceed
       Object proceed = jp.proceed();
       System.out.println("環(huán)繞后");
       System.out.println(proceed);
  }
}

第二步:在Spring配置文件中绊茧,注冊(cè)bean铝宵,并增加支持注解的配置

<!--第三種方式:注解實(shí)現(xiàn)-->
<bean id="annotationPointcut" class="com.kuang.config.AnnotationPointcut"/>
<!--開啟注解支持-->
<aop:aspectj-autoproxy/>

aop:aspectj-autoproxy:說明

通過aop命名空間的<aop:aspectj-autoproxy />聲明自動(dòng)為spring容器中那些配置@aspectJ切面的bean創(chuàng)建代理,織入切面华畏。當(dāng)然鹏秋,spring 在內(nèi)部依舊采用AnnotationAwareAspectJAutoProxyCreator進(jìn)行自動(dòng)代理的創(chuàng)建工作,但具體實(shí)現(xiàn)的細(xì)節(jié)已經(jīng)被<aop:aspectj-autoproxy />隱藏起來了

<aop:aspectj-autoproxy />有一個(gè)proxy-target-class屬性亡笑,默認(rèn)為false侣夷,表示使用jdk動(dòng)態(tài)代理織入增強(qiáng),當(dāng)配為<aop:aspectj-autoproxy  poxy-target-class="true"/>時(shí)仑乌,表示使用CGLib動(dòng)態(tài)代理技術(shù)織入增強(qiáng)百拓。不過即使proxy-target-class設(shè)置為false,如果目標(biāo)類沒有聲明接口晰甚,則spring將自動(dòng)使用CGLib動(dòng)態(tài)代理衙传。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市厕九,隨后出現(xiàn)的幾起案子蓖捶,更是在濱河造成了極大的恐慌,老刑警劉巖止剖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腺阳,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡穿香,警方通過查閱死者的電腦和手機(jī)亭引,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來皮获,“玉大人焙蚓,你說我怎么就攤上這事∪鞅Γ” “怎么了购公?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)雁歌。 經(jīng)常有香客問我宏浩,道長(zhǎng),這世上最難降的妖魔是什么靠瞎? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任比庄,我火速辦了婚禮求妹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘佳窑。我一直安慰自己制恍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布神凑。 她就那樣靜靜地躺著净神,像睡著了一般。 火紅的嫁衣襯著肌膚如雪溉委。 梳的紋絲不亂的頭發(fā)上鹃唯,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音瓣喊,去河邊找鬼俯渤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛型宝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播絮爷,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼趴酣,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了坑夯?” 一聲冷哼從身側(cè)響起岖寞,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柜蜈,沒想到半個(gè)月后仗谆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡淑履,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年隶垮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秘噪。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狸吞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出指煎,到底是詐尸還是另有隱情蹋偏,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布至壤,位于F島的核電站威始,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏像街。R本人自食惡果不足惜黎棠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一晋渺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧葫掉,春花似錦些举、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至挪挤,卻和暖如春叼丑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扛门。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工鸠信, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人论寨。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓星立,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親葬凳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绰垂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容