還在面向?qū)ο螅嫦蚯衅私庖幌?/h1>

1、什么是AOP?(是什么)

???Aspect OrientedProgramming的縮寫,意思就是:面向切面編程肥惭,通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)舅巷。這種在運行時套硼,動態(tài)地將代碼切入到類的指定方法垫毙、指定位置上的編程思想就是面向切面的編程霹疫。它是一種編程范式,一種編程思想综芥。AOP是Spring提供的關(guān)鍵特性之一丽蝎。對了,有人提到這個和攔截器有什么關(guān)系膀藐,注意AOP是一種編程思想屠阻,攔截器就是基于這種編程思想實現(xiàn)的。

基本概念:
    切面(Aspect):一個關(guān)注點的模塊化额各,這個關(guān)注點可能會橫切多個對象国觉。

    連接點(Joinpoint):程序執(zhí)行過程中的某個特定的點

    通知(Advice):在切面的某個特定的連接點上執(zhí)行的動作。
image
    切入點(Pointcut): 匹配連接點的斷言虾啦,在AOP中通知和一個切入點表達(dá)式的關(guān)聯(lián)麻诀。

    引入(Introduction)在不修改類代碼的前提下,為類添加新的方法和屬性缸逃。

    目標(biāo)對象(target Object)被一個或者多個切面所通知的對象

      AOP代理(Aop proxy)AOP框架創(chuàng)建的對象针饥,用來實現(xiàn)切面契約(aspectcontract)包括通知放法執(zhí)行等功能。

   織入(weaving)  把切面連接到其他的應(yīng)用程序類型或者對象上需频,并創(chuàng)建一個被通知的對象丁眼,分為編制時織入,類加載時織入昭殉,執(zhí)行時織入苞七。

2、aop編程思想的作用E捕(為什么)

???其實aop就是對OOP編程的有效補充蹂风。其實最終目的是實現(xiàn)程序的解耦。但是OOP一般允許開發(fā)者定義縱向的關(guān)系乾蓬,但并不適合定義橫向關(guān)系惠啄,使用AOP技術(shù)可以將一些系統(tǒng)性相關(guān)的編程工作、獨立提取出來任内,獨立實現(xiàn)撵渡,然后通過切面切入進(jìn)系統(tǒng)。從而避免了在業(yè)務(wù)邏輯的代碼中混入很多的系統(tǒng)相關(guān)的邏輯——比如權(quán)限管理死嗦,事物管理趋距,日志記錄等等。這些系統(tǒng)性的編程工作都可以獨立編碼實現(xiàn)越除,然后通過AOP技術(shù)切入進(jìn)系統(tǒng)即可节腐。從而達(dá)到了 將不同的關(guān)注點分離出來的效果外盯。

image

???如上圖,我們可以將日志以及權(quán)限這種分離出來翼雀,然后在需要用到的這些核心功能模塊中橫向的切入進(jìn)去饱苟,這樣對于核心模塊是無感的,這樣的話講大大降低系統(tǒng)的耦合性和復(fù)雜性锅纺,試想如果這些模塊散落在各個核心業(yè)務(wù)中掷空,如果出現(xiàn)大的改動,必然會產(chǎn)生極大的維護(hù)成本囤锉,需要每一處都進(jìn)行修改坦弟。

3、實現(xiàn)方式

** 方式一:**@AspectJ注解驅(qū)動的切面官地,這個是一種靜態(tài)代理的方式

???Java通過Java編譯器將.java源文件編譯成.class字節(jié)碼文件酿傍,這種.class文件是二進(jìn)制文件,內(nèi)容是只有JVM虛擬機能夠識別的機器碼驱入,JVM虛擬機讀取字節(jié)碼文件赤炒,取出二進(jìn)制數(shù)據(jù),加載到內(nèi)存中亏较,解析.class文件內(nèi)的信息莺褒,生成對應(yīng)的Class對象,進(jìn)而使Class對象創(chuàng)建類的具體實例來進(jìn)行調(diào)用實現(xiàn)具體的功能雪情。
???所以這種方式就是在java編譯成class的時候去實現(xiàn)代理遵岩。性能上很高效,但是沒有不太靈活巡通。
???這種方式我的理解就是在編譯器將切片插入到對應(yīng)的函數(shù)棧中(僅僅自己的理解)

** 方式二:**運行期動態(tài)代理尘执,(JDK動態(tài)代理,CGLib動態(tài)代理)

  1. 純jiava的實現(xiàn)宴凉,無需特殊的編譯過程誊锭,不需要控制類加載器層次。

  2. 目前只支持放法執(zhí)行連接點弥锄,(通知spring bean的方法的執(zhí)行)

  3. 不是提供一個最完整的AOP實現(xiàn)盡管它已經(jīng)非常強大丧靡,而是側(cè)重用于提供一種AOP實現(xiàn)和SpringIOC容器之間的整合,用于幫助解決企業(yè)應(yīng)用中常見的問題籽暇。

  4. Spring AOP 不會和Aspect競爭温治,從而提供綜合全面的AOP解決方案。

image

???spring中AOP代理由Spring的IOC容器負(fù)責(zé)生成图仓,管理,其依賴關(guān)系也是由IOC容器負(fù)責(zé)管理的但绕,因此救崔,AOP代理可以直接使用容器中的其他bean實例作為目標(biāo)惶看,這種關(guān)系可由IOC容器的依賴注入提供,Spring創(chuàng)建代理的規(guī)則為:

1)六孵、默認(rèn)使用java動態(tài)代理來創(chuàng)建AOP代理纬黎,這樣就可以為任何接口實例創(chuàng)建代理了。
2)劫窒、當(dāng)需要代理的類不是代理接口的時候本今,Spring會切換為使用CGLB代理,也可強制使用CGLIB(CGLIB是一個強大的主巍、高性能的代碼生成庫)

4冠息、應(yīng)用場景

image

???其實這里有點多余,aop是一種編程思想孕索,你可以在很多場景中去使用逛艰,但是還是想給大家一個直觀的感受。

5搞旭、在sping中使用切面編程散怖。(怎么用?)

基于@AspectJ注解的AOP實現(xiàn)
???這里主要是采用這種方式來演示aop的實現(xiàn)過程肄渗,來直觀的體會aop實現(xiàn)的思想镇眷。

step1:引用依賴

    <!--aop    aspectj-->   
 <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
    <dependency>        
       <groupId>aopalliance</groupId> 
       <artifactId>aopalliance</artifactId>
       <version>1.0</version>
    </dependency>    
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.1.3.RELEASE</version>
    </dependency>

Step2:創(chuàng)建測試類

IAopTest.java 接口

package com.mjcc.spring.aop;
/** 
* @Description:
* @Author: chengcheng 
* @Date: Create in 8:40 2019/7/28
* @Modified By: 
*/
public interface IAopTest {
    public int add(int a, int b);
    public int sub(int a, int b);
}

AopTestImpl.java 實現(xiàn)類

package com.mjcc.spring.aop;import org.springframework.stereotype.Component;
/**
 * @Description:
 * @Author: chengcheng
 * @Date: Create in 8:42 2019/7/28
 * @Modified By:
 */
@Component("aopTest")
public class AopTestImpl implements IAopTest {
    public int add(int a, int b) {
        int res = a + b; 
        return res;
    }
    public int sub(int a, int b) { 
        int res = a - b;
        return res;
    }
}

LoggerAspect.java // 日志的切面編程

package com.mjcc.spring.aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;import java.util.Arrays;
import java.util.List;
/** 
* @Description: 
* @Author: chengcheng 
* @Date: Create in 8:59 2019/7/28 
* @Modified By:
 */
@Aspect     
// 告訴spring  這是一個切面類,就是橫切關(guān)注點的集合翎嫡,與核心業(yè)務(wù)代碼無關(guān)的日志欠动,權(quán)限,事務(wù)代碼 集中起來組成切面
@Componentpublic
 class LoggerAspect {
    private Logger logger = Logger.getLogger(this.getClass());
    // 指定beforeMethod在哪個類中的哪個方法前切入執(zhí)行 
   // @Before的參數(shù)里钝的,寫一個切入點表達(dá)式翁垂,來告訴spring 要將下面的方法切入到哪個類的哪個方法前面執(zhí)行
    @Before("execution(public int com.mjcc.spring.aop.AopTestImpl.add(int, int))")
    @Before("execution(public int com.mjcc.spring.aop.AopTestImpl.*(int, int))")
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName(); // 拿到切入點的的方法名 
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        logger.info(methodName + "方法運算執(zhí)行之前。硝桩。沿猜。。碗脊。啼肩。。" + args);
    }
}

測試base類

package com.mjcc.spring.base;

import org.junit.After;
import org.junit.Before;
import org.springframework.beans.BeansException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StringUtils;

/**
 * @Description:
 * @Author: chengcheng
 * @Date: Create in 14:18 2019-04-13
 * @Modified By:
 */
public class UnitTestBase {
    private ClassPathXmlApplicationContext context;
    private String springXmlPath;
    public UnitTestBase () {
    }

    public UnitTestBase(String springXmlPath) {
        this.springXmlPath = springXmlPath;
    }

    @Before // 初始化方法衙伶,執(zhí)行當(dāng)前測試類的每個測試方法前執(zhí)行
    public void before () {
        if (StringUtils.isEmpty(springXmlPath)) {
            springXmlPath = "classpath*:spring-*.xml";
        }
        try {
            context = new ClassPathXmlApplicationContext(springXmlPath.split("[,\\s]+"));
            context.start();
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }

    @After //釋放資源祈坠,執(zhí)行當(dāng)前測試類的每個測試方法后執(zhí)行
    public void after () {
        context.destroy();
    }

    @SuppressWarnings("unchecked")
    protected  <T extends Object> T getBean (String beanId) {
        try {
            return (T)context.getBean(beanId);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }

    protected <T extends Object> T getBean (Class<T> clazz) {
        try {
            return context.getBean(clazz);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }


}

測試類:

package com.mjcc.spring.aop;

import com.mjcc.spring.base.UnitTestBase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

/**
 * @Description:
 * @Author: chengcheng
 * @Date: Create in 8:47 2019/7/28
 * @Modified By:
 */
@RunWith(BlockJUnit4ClassRunner.class)
public class AopTestImplTest extends UnitTestBase {
    public AopTestImplTest () {
        super("applicationContext.xml");
    }
    @Test
    public void AopTest () {
        IAopTest aopTest = (IAopTest) super.getBean("aopTest");
        System.out.println("add :  " + aopTest.add(1, 1));
        System.out.println("sub :  " + aopTest.sub(8, 5));
    }
}

xml配置

<?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:context="http://www.springframework.org/schema/context"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan base-package="com.mjcc.spring"></context:component-scan>
    <!--自動生成aspecyj 動態(tài)代理-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

切入點:

  • @Before和它注解的這個方法在AOP中叫做通知,在上面基礎(chǔ)概念中已經(jīng)提到了矢劲, before屬于前置通知赦拘。

還有下面這些通知,

  • @After 后置通知芬沉,在目標(biāo)方法執(zhí)行之后執(zhí)行

  • @AfterReturning 返回通知躺同,(在目標(biāo)方法返回結(jié)果之后執(zhí)行)

  • @AfterThrowing異步通知阁猜,在目標(biāo)方法拋出異常之后執(zhí)行

  • @Around 環(huán)繞通知

???對了,注意一個問題蹋艺,當(dāng)同一個目標(biāo)方法有多個切面的時候剃袍,到底是哪個先執(zhí)行,這個順序可以使用@Order注解來注解切入類捎谨,值越小民效,越先執(zhí)行。@Order(1) > @Order(2)

個人拙見涛救,望指教畏邢。
關(guān)注公眾號回復(fù)獲取“java入門就業(yè)”獲取一套個人收藏的java視頻教程 ,

這里是一個遠(yuǎn)離軟紅香土州叠,尋找寧靜致遠(yuǎn)的小空間棵红,歡 迎大家一起交流。分享故事咧栗,分享心境逆甜。
相識,必然知味致板;相知交煞,必然知心;相處斟或,必然知情素征。
服務(wù)號
訂閱號
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末,一起剝皮案震驚了整個濱河市萝挤,隨后出現(xiàn)的幾起案子御毅,更是在濱河造成了極大的恐慌,老刑警劉巖怜珍,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件端蛆,死亡現(xiàn)場離奇詭異,居然都是意外死亡酥泛,警方通過查閱死者的電腦和手機今豆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柔袁,“玉大人呆躲,你說我怎么就攤上這事〈匪鳎” “怎么了插掂?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我辅甥,道長箩祥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任肆氓,我火速辦了婚禮,結(jié)果婚禮上底瓣,老公的妹妹穿的比我還像新娘谢揪。我一直安慰自己,他們只是感情好捐凭,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布拨扶。 她就那樣靜靜地躺著,像睡著了一般茁肠。 火紅的嫁衣襯著肌膚如雪患民。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天垦梆,我揣著相機與錄音匹颤,去河邊找鬼。 笑死托猩,一個胖子當(dāng)著我的面吹牛印蓖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播京腥,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼赦肃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了公浪?” 一聲冷哼從身側(cè)響起他宛,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎欠气,沒想到半個月后厅各,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡晃琳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年讯检,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卫旱。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡人灼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出顾翼,到底是詐尸還是另有隱情投放,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布适贸,位于F島的核電站灸芳,受9級特大地震影響涝桅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜烙样,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一冯遂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谒获,春花似錦蛤肌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赔硫,卻和暖如春炒俱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爪膊。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工权悟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人推盛。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓僵芹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親小槐。 傳聞我的和親對象是個殘疾皇子拇派,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

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