Spring之AOP

前言

繼續(xù)引用上一篇博客的代碼(Spring之IOC

源代碼目錄結(jié)構(gòu)如下:

main
    service
        UserService
    dao
        UserDao(接口)
        UserDaoImpl
    model
        User
    beans.xml

日志引發(fā)的問(wèn)題

如果有這樣一個(gè)需求:在保存用戶到數(shù)據(jù)庫(kù)之前添加日志,怎么做?

  • 直接修改源代碼
  • 繼承,重寫方法
  • 組合,裝飾者模式

如果有幾百個(gè)方法等著我們?nèi)ゼ尤罩荆趺崔k?
Spring為我們提供了一種方法:面向切面編程,也就是傳說(shuō)中的AOP。
在談AOP之前,我們簡(jiǎn)單談一下JDK中動(dòng)態(tài)代理的實(shí)現(xiàn)方式,AOP就是通過(guò)動(dòng)態(tài)代理技術(shù)實(shí)現(xiàn)面向切面編程的。

動(dòng)態(tài)代理

在日志問(wèn)題中,我們也可以通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)。
代理充當(dāng)著一個(gè)中間人的角色,在使用代理時(shí)我們可以執(zhí)行一些額外操作,Java的動(dòng)態(tài)代理可以動(dòng)態(tài)的處理方法調(diào)用,將所有對(duì)方法的調(diào)用重定向到單一的調(diào)用處理器上。
代碼如下:
測(cè)試代碼

@Test
public void testProxy() {
    UserDao userDao = new UserDaoImpl();
    // 獲得一個(gè)動(dòng)態(tài)代理
    UserDao proxy = (UserDao)Proxy.newProxyInstance(
            userDao.getClass().getClassLoader(),
            new Class[]{UserDao.class},
            new DynamicProxyHandle(userDao));
    proxy.save(new User());
}

事件處理類

public class DynamicProxyHandle  implements InvocationHandler{
    private Object target;// 代理目標(biāo)

    public DynamicProxyHandle(Object target) {// 通過(guò)構(gòu)造方法傳參
        this.target = target;
    }
    // 所有對(duì)目標(biāo)的方法調(diào)用都會(huì)重定向到此方法上
    // 故我們可以在原方法執(zhí)行之前或之后添加一些邏輯
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("動(dòng)態(tài)代理中");
        return method.invoke(target,args);
    }
}

Spring AOP

先不說(shuō)AOP的核心概念,我們看一下通過(guò)Spring AOP怎么實(shí)現(xiàn)日志的添加呢?我們有兩種方式來(lái)實(shí)現(xiàn)Spring中AOP的配置。

通過(guò)XML和Annotation配置AOP

Annotation
既然是面向切面編程,首先我們先構(gòu)造一個(gè)切面,我們把什么切進(jìn)去呢?就是我們的業(yè)務(wù)邏輯-日志服務(wù)。我們希望在添加用戶之前收到一條日志。
需要在XML文件中聲明的幾條。

    <!--下面這行告訴Spring使用注解配置-->
    <context:annotation-config>
    </context:annotation-config>
    <!--下面這行告訴Spring在main包下自動(dòng)尋找bean-->
    <context:component-scan base-package="main.*">
    </context:component-scan>
    <!--aspectj的聲明-->
    <aop:aspectj-autoproxy/>

下面為切面及切點(diǎn)代碼

/**
 * 基于annotation的AOP配置
 */
@Component
@Aspect  // 這是一個(gè)切面(aspect)
public class LogIntercepor {
    // 定義一個(gè)切點(diǎn)(PointCut)
    @Pointcut("execution(public void main.dao.UserDaoImpl.save(main.model.User))")
    public void my(){}

    // 通知(advice)
    @Before("my()")
    public void before() {
        System.out.println("Method before~");
    }

    @AfterReturning("my()")
    public void after() {
        System.out.println("Method after~");
    }
}

在上述代碼中出現(xiàn)了一些AOP的核心概念,在此列舉一下:

  1. 通知(advice)
    定義了切面要完成的工作,就是告訴spring什么時(shí)候做什么事。
    在Spring中有五種類型通知:

    • Before
    • After
    • After-returning
    • After-throwing
    • Around
  2. 切點(diǎn)(pointcut)
    在日志服務(wù)中就是那個(gè)我想加入日志的地方。

  3. 切面(aspect)
    試想,我們把一個(gè)切面切進(jìn)了應(yīng)用程序中,這個(gè)切面就是日志服務(wù)。

  4. 引入(IIntroduction)

  5. 織入(weaving )

XML

一個(gè)切面類

/**
 * 切面
 */
public class LogInterceporXML {

    public void before() {
        System.out.println("XML add before~");
    }
}

XML中的配置

<!--首先需要這么一行支持aspectj的自動(dòng)代理-->
<aop:aspectj-autoproxy/>
<!--聲明我們的切面的bean對(duì)象-->
<bean id="interceporXML" class="main.aop.LogInterceporXML"></bean>
<aop:config>
    <!--聲明切點(diǎn)-->
    <aop:pointcut id="add"
                  expression="execution(public void main.service.UserService.add(..))"/>
    <!--聲明切面-->
    <aop:aspect
            ref="interceporXML">
    <!--在方法執(zhí)行之前執(zhí)行我們的方法-->
        <aop:before method="before" pointcut-ref="add"></aop:before>
    </aop:aspect>
</aop:config>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,568評(píng)論 19 139
  • 本章內(nèi)容: 面向切面編程的基本原理 通過(guò)POJO創(chuàng)建切面 使用@AspectJ注解 為AspectJ切面注入依賴 ...
    謝隨安閱讀 3,425評(píng)論 0 9
  • **** AOP 面向切面編程 底層原理 代理!?。?今天AOP課程1、 Spring 傳統(tǒng) AOP2、 Spri...
    luweicheng24閱讀 1,506評(píng)論 0 1
  • 濃情蜜意時(shí)朝朝暮暮 兩相生厭時(shí)分分鐘鐘 花兒繁盛到開 絢爛到天際 又終究要落敗 卑微到塵埃 新日從晨到夕 璀璨一世...
    回憶成繭閱讀 384評(píng)論 4 3
  • 水墨凝香8閱讀 146評(píng)論 0 0

友情鏈接更多精彩內(nèi)容