最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring基礎之AOP的概念介紹

 更新時間:2022年06月12日 07:49:29   作者:御狐神  
AOP是Spring的關鍵特性之一,雖然Spring的IOC特性并不依賴于AOP,本文重點介紹AOP編程中的一些術語,這些術語不僅僅局限于Spring,它適用于所有的AOP編程,感興趣的朋友一起看看吧

Spring容器包含兩個重要的特性:面向切面編程(AOP)和控制反轉(IOC)。面向切面編程是面向對象(OOP)的一種補充,在面向對象編程的過程中編程針對的目標是一個個對象,而面向切面編程中編程針對的目標是一個個切面。切面支持跨類型跨對象(如事務的切面可以加在任何地方)進行模塊化。

前言

AOP是Spring的關鍵特性之一,雖然Spring的IOC特性并不依賴于AOP(意味著你可以只使用Spring的IOC特性而不使用AOP特性),但是二者結合起來可以靈活的實現很多中間件解決方案。比如我們經常使用的事務(@Transaction),就是通過AOP方案實現的。本文重點介紹AOP編程中的一些術語,這些術語不僅僅局限于Spring,它適用于所有的AOP編程。

  • 切面(Aspect):面向切面編程可以跨類跨對象進行切面編程,一個切面就是對一類橫切關注點的模塊化。
  • 切入點(JoinPoint):程序執(zhí)行過程中的一個點,如方法調用、字段訪問和異常拋出等。
  • 增強(Advice):用于對切面增強,包含前增強、后增強和環(huán)繞增強。大多數AOP框架會對切入點進行攔截,并在切入點維護一個攔截器鏈。
  • 目標對象(TargetObject):包含一個或者多個切面的對象。
  • AOP代理(AOPProxy):通過Java動態(tài)代理或者CGLib增強得到的代理對象。
  • 織入(Weaving):將切面整合到完整的流執(zhí)行流程。

Spring的AOP的功能和目標

Spring的AOP使用純Java語言實現(如AspectJ就不是Java語言),不需要任何額外的編譯流程,不需要修改類加載器,適用于任何Servlet容器和應用服務。Spring的AOP只支持方法攔截,不支持字段攔截,如果用戶需要使用字段攔截,可以考慮引入AspectJ等類似的框架。

Spring的AOP框架和其它的框架有些不同,Spring的Aop框架不僅僅是為了提供一個AOP功能,它更重要的功能是和Spring的IOC容器結合,提供一些企業(yè)應用服務的解決方案(如事務等),我們可以和定義一個普通Bean一樣的方式去定以一個切面。Spring的AOP不支持非常細粒度的AOP,只支持對容器中的Bean進行AOP,如果需要更細粒度的AOP,可以考慮使用AspectJ。Spring容器的一個優(yōu)秀的特性就是非侵入性,所以你可以靈活的選擇自己的AOP方案,不一定非要使用Spring的方案。

代理方式

Spring對實現接口的方法默認使用Java動態(tài)代理實現AOP攔截,對于非接口方法則會使用CGLIB字節(jié)碼工具實現代理。

@AspectJ的支持

@AspectJ注解可以把一個普通的Java類聲明為切面。@AspectJ注解是AspectJ5引入的注解,Spring雖然可以讀取AspectJ5的注解用于切面元數據的配置,但是在運行的時候使用的仍然是Spring AOP進行代理,而沒有使用AspectJ的編譯器或者織入邏輯。我們會在后續(xù)討論如何在Spring中使用AspectJ的編譯器和織入邏輯。

啟用@AspectJ

Spring默認沒有啟用AspectJ,如果你需要Spring支持@AspectJ注解對應的切面,可以通過在配置類上添加注解或者使用XML啟用配置(AspectJ所在的包是:aspectjweaver.jar)。

通過Java注解啟用AspectJ注解支持:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}

通過XML配置啟用AspectJ注解

<aop:aspectj-autoproxy/>

定義一個切面

當啟用AspectJ支持之后,開發(fā)者定義的任何Aspect切面會自動地被檢測到,然后Spring AOP會對切面進行攔截。下面兩個例子展示了如何配置AspectJ切面,你可以通過添加@Component注解把切面Bean注冊到Spring容器中。

<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
    <!-- configure properties of the aspect here -->
</bean>
package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class NotVeryUsefulAspect {

}

聲明一個切入點

切入點程序運行過程中我們感興趣的一個點,Spring的AOP框架只支持發(fā)現對Spring Bean方法上的切入點,因此你可以簡單的把切入點理解為SpringBean的方法。

切入點確定感興趣的連接點,從而使我們能夠控制何時運行通知。springaop只支持springbean的方法執(zhí)行連接點,因此可以將切入點看作與springbean上方法的執(zhí)行相匹配。切入點聲明由兩部分組成:一部分是由名稱和任何參數組成的簽名,另一部分是確定我們感興趣的方法執(zhí)行的切入點表達式。在AOP的@AspectJ注釋樣式中,切入點簽名由常規(guī)方法定義提供,切入點表達式由@pointcut注釋指示(用作切入點簽名的方法必須具有void返回類型)。切入點由兩部分組成,一部分是用于區(qū)別不同切入點的標識(下面例子中的 private void anyOldTransfer() {} )),另外一部分是確定我們感興趣的Bean方法的表達式(下面例子中的 @Pointcut("execution(* transfer(..))") ), 下面的例子展示了一個切入點的定義:

@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature

Spring匹配切入點的語法使用了AspectJ5中的表達式語法,我們可以參考AspectJ文檔相關的語法.

常見的切入點匹配表達

Spring支持下面常見的AspectJ切面定義語法:

  • execution:用于匹配方法的連接點。
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}
  • within:用于匹配類型內的方法。
@Pointcut("within(com.xyz.myapp.trading..*)")
private void inTrading() {}
  • this:匹配當前AOP代理對象的執(zhí)行方法
@target(org.springframework.transaction.annotation.Transactional)
  • target:target匹配目標對象的類型,即被代理對象的類型,例如A繼承了B接口,則使用target("B"),target("A")均可以匹配到A
//    當前AOP對象實現了 IPointcutService接口的任何方法
@Pointcut("target(cn.javass.spring.chapter6.service.IPointcutService)")
private void anyPublicOperation() {}
  • args:用于限定切點方法的參數類型。
args(java.io.Serializable)
  • @target:被代理對象應該包含指定的注解。
@target(org.springframework.transaction.annotation.Transactional)
  • @args: 被代理對象的參數包含指定的注解。
@args(com.xyz.security.Classified)
  • @within: 被代理的對象應包含指定注解
@within(org.springframework.transaction.annotation.Transactional)
  • @annotation:切入點包含指定的注解。
@annotation(org.springframework.transaction.annotation.Transactional)

我們可以通過“&&”和“||”對多個條件進行組合,AspectJ還有很多其它的表達式,但是Spring不支持除上述表達式以外的其它表達式。AspectJ其它表達式包含: call, get, set, preinitialization, staticinitialization, initialization, handler, adviceexecution, withincode, cflow, cflowbelow, if, @this, @withincode等。

我們在使用Spring的代理方法之前,應該知道其代理原理。Java動態(tài)代理只能攔截public接口方法上的調用,CGLib只能攔截public、protected和defult方法。如果你需要更深層次的攔截,可以考慮使用底層的Aspectj。

切面的增強

我們在上面的步驟定義好了一個切入點,我們現在就可以對這個切入點進行額外操作,這些額外操作被稱為增強,Spring支持四種增強方式:前增強、后增強、異常增強和環(huán)繞增強。Spring支持在增強方法的定義上直接定義切入點。

前增強BeforeAdvice

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
    @Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
    public void doAccessCheck() {
        // ...
    }
}
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {

    @Before("execution(* com.xyz.myapp.dao.*.*(..))")
    public void doAccessCheck() {
        // ...
    }
}

后增強

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class AfterReturningExample {
    @AfterReturning(
        pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()",
        returning="retVal")
    public void doAccessCheck(Object retVal) {
        // ...
    }
}

異常增強

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
@Aspect
public class AfterThrowingExample {
    @AfterThrowing(
        pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()",
        throwing="ex")
    public void doRecoveryActions(DataAccessException ex) {
        // ...
    }
}

環(huán)繞增強

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class AroundExample {
    @Around("com.xyz.myapp.CommonPointcuts.businessService()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        // start stopwatch
        Object retVal = pjp.proceed();
        // stop stopwatch
        return retVal;
    }
}

代理機制

我們前面說過,Spring AOP通過動態(tài)代理和CGLIB實現AOP對象的代理。我們可以通過如下配置設置動態(tài)代理全部走CGLIB。

<aop:config proxy-target-class="true">
    <!-- other beans defined here... -->
</aop:config>

代理工廠的使用

Spring AOP實現代理的核心類是 AspectJProxyFactory ,我們可以使用這個類編程式生成代理對象:

// create a factory that can generate a proxy for the given target object
AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);

// add an aspect, the class must be an @AspectJ aspect
// you can call this as many times as you need with different aspects
factory.addAspect(SecurityManager.class);

// you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspect
factory.addAspect(usageTracker);

// now get the proxy object...
MyInterfaceType proxy = factory.getProxy()

到此這篇關于Spring基礎之AOP的概念介紹的文章就介紹到這了,更多相關spring aop概念內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java中ResultSetMetaData 元數據的具體使用

    Java中ResultSetMetaData 元數據的具體使用

    本文主要介紹了Java中ResultSetMetaData 元數據的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • 開發(fā)者必讀:揭秘Python與Java的性能較量

    開發(fā)者必讀:揭秘Python與Java的性能較量

    本文將探討這兩種流行的編程語言之間的性能差異,無論你是剛剛入門編程還是已經有一定經驗,這個指南都將幫助你了解Python和Java在執(zhí)行速度、內存管理以及擴展性方面的不同,通過比較這兩種語言的特點和優(yōu)勢,你將能夠更好地選擇適合自己項目需求的編程語言,讓我們開始吧!
    2023-12-12
  • java Servlet 實現動態(tài)驗證碼圖片示例

    java Servlet 實現動態(tài)驗證碼圖片示例

    這篇文章主要介紹了java Servlet 實現動態(tài)驗證碼圖片示例的資料,這里整理了詳細的代碼,有需要的小伙伴可以參考下。
    2017-02-02
  • 如何兩步解決maven依賴導入失敗的問題

    如何兩步解決maven依賴導入失敗的問題

    這篇文章主要介紹了如何兩步解決maven依賴導入失敗的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • mybatis簡單resultMap使用詳解

    mybatis簡單resultMap使用詳解

    resultMap是Mybatis最強大的元素,它可以將查詢到的復雜數據(比如查詢到幾個表中數據)映射到一個結果集當中。這篇文章主要介紹了mybatis簡單resultMap使用詳解的相關資料,需要的朋友可以參考下
    2021-04-04
  • Spring Boot集成redis,key自定義生成方式

    Spring Boot集成redis,key自定義生成方式

    這篇文章主要介紹了Spring Boot集成redis,key自定義生成方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringCloudAlibaba微服務調用組件OpenFeign的方法

    SpringCloudAlibaba微服務調用組件OpenFeign的方法

    Feign是Netflix開發(fā)的聲明式、模板化的HTTP客戶端,其靈感來自Retrofit、JAXRS-2.0以及WebSocket,Feign可幫助我們更加便捷、優(yōu)雅地調用HTTP API,這篇文章主要介紹了SpringCloudAlibaba微服務調用組件OpenFeign,需要的朋友可以參考下
    2024-07-07
  • MyBatis一級與二級緩存相關配置

    MyBatis一級與二級緩存相關配置

    mybatis-plus是一個Mybatis的增強工具,在Mybatis的基礎上只做增強不做改變,為簡化開發(fā)、提高效率而生,這篇文章帶你了解Mybatis的一級和二級緩存
    2023-01-01
  • Java輸出Hello World完美過程解析

    Java輸出Hello World完美過程解析

    當我們學習一門編程語言的時候,我們都會先學如何輸出Hello World!本文通過幾個例子給大家介紹輸出Hello World的代碼,感興趣的朋友一起看看吧
    2021-06-06
  • 十分鐘理解Java中的動態(tài)代理

    十分鐘理解Java中的動態(tài)代理

    十分鐘幫助大家理解Java中的動態(tài)代理,什么是動態(tài)代理?感興趣的小伙伴們可以參考一下
    2016-06-06

最新評論

寿宁县| 永年县| 宣武区| 利辛县| 重庆市| 石棉县| 濉溪县| 沁源县| 水城县| 沾益县| 西华县| 博客| 建德市| 台东市| 河源市| 南木林县| 进贤县| 宾川县| 乌海市| 东至县| 天台县| 抚远县| 白山市| 灵石县| 彭水| 建平县| 扎赉特旗| 烟台市| 合川市| 南陵县| 临安市| 勐海县| 分宜县| 鹤岗市| 汽车| 米泉市| 深水埗区| 乳源| 三台县| 浮山县| 新安县|