溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring?AOP的概念與實(shí)現(xiàn)過(guò)程是什么

發(fā)布時(shí)間:2023-02-22 11:48:49 來(lái)源:億速云 閱讀:126 作者:iii 欄目:開(kāi)發(fā)技術(shù)

今天小編給大家分享一下Spring AOP的概念與實(shí)現(xiàn)過(guò)程是什么的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

Aop

什么是Aop?

AOP就是面向切面編程,通過(guò)預(yù)編譯方式以及運(yùn)行期間的動(dòng)態(tài)代理技術(shù)來(lái)實(shí)現(xiàn)程序的統(tǒng)一維護(hù)功能。

什么是切面,我理解的切面就是兩個(gè)方法之間,兩個(gè)對(duì)象之間,兩個(gè)模塊之間就是一個(gè)切面。假設(shè)在兩個(gè)模塊之間需要共同執(zhí)行一系列操作,并且最后將這一系列操作注入到兩個(gè)模塊之間的指定位置。此時(shí)這一系列操作就是切面,注入這些操作的位置稱之為切點(diǎn)。

舉例:公司員工上班

A員工上班需要在前臺(tái)進(jìn)行打卡,同樣的B員工…其他員工都需要在前臺(tái)打卡,那么如果為每一位員工提供單獨(dú)的打卡通道就有些過(guò)于浪費(fèi)資源。像這樣

Spring?AOP的概念與實(shí)現(xiàn)過(guò)程是什么

于是,在前臺(tái)這個(gè)位置設(shè)置接口,聲明公共的打卡方法,所有員工共同通過(guò)該接口進(jìn)行打卡,那么在打卡時(shí)的一系列校驗(yàn)或者記錄的整個(gè)操作就可以被稱之為切面,前臺(tái)這個(gè)空間位置就被稱之為切點(diǎn),如下圖所示

Spring?AOP的概念與實(shí)現(xiàn)過(guò)程是什么

aop主要作用就是進(jìn)行日志記錄、事務(wù)/異常處理等功能以便更好地維護(hù)開(kāi)發(fā),主要目的就是將這些行為從項(xiàng)目的業(yè)務(wù)邏輯代碼中分離出來(lái)并且降低各個(gè)業(yè)務(wù)邏輯模塊之間的耦合度。保證在執(zhí)行aop操作的同時(shí)不會(huì)影響到項(xiàng)目的業(yè)務(wù)邏輯代碼

幾個(gè)概念

Aspect:切面 Aspect中會(huì)包含一些pointCut切入點(diǎn)以及一些Advice

Advice:通知 切面需要完成的工作,通過(guò)before、after、around來(lái)區(qū)別是在連接點(diǎn)之前或者之后 或者環(huán)繞

Target:目標(biāo) 目標(biāo)對(duì)象,該對(duì)象會(huì)被織入advice

PointCut:切點(diǎn) 即切面通知執(zhí)行的地點(diǎn) advice將會(huì)在這里發(fā)生

JointPoint:連接點(diǎn) 所有方法的執(zhí)行點(diǎn)

PointCut用來(lái)修飾JointPoint,PointCut是advice執(zhí)行的點(diǎn),而JointPoint表示所有方法的執(zhí)行點(diǎn),通過(guò)PointCut可以確定哪些JointPoint是可以被織入的點(diǎn)

我們通常不希望advice會(huì)在所有的JointPoint點(diǎn)執(zhí)行,PointCut的作用就是可以進(jìn)行校驗(yàn)來(lái)更精準(zhǔn)的匹配執(zhí)行點(diǎn)。簡(jiǎn)單概括就是Jointpoint可以執(zhí)行但未必執(zhí)行,只有PointCut匹配到了JointPoint才可以在該點(diǎn)執(zhí)行

Aspect切面可以理解為PointCut+Advice

使用AOP織入導(dǎo)入包

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

實(shí)現(xiàn)aop方式一

使用spring內(nèi)置的API接口

準(zhǔn)備:UserService、UserServiceImpl簡(jiǎn)單實(shí)現(xiàn)CRUD

在spring核心配置文件applicationContext.xml中配置aop:

<?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      https://www.springframework.org/schema/beans/spring-beans.xsd                     http://www.springframework.org/schema/aop                  https://www.springframework.org/schema/aop/spring-aop.xsd">
  <bean id="userServiceImpl" class="com.mount.service.UserServiceImpl"/>
  <bean id="log" class="com.mount.log.log"/>
  <bean id="afterLog" class="com.mount.log.AfterLog"/>
  <!--  配置AOP  -->
  <aop:config>
    <!-- 切入點(diǎn) expression表達(dá)式  表示從哪里開(kāi)始執(zhí)行   -->
    <aop:pointcut id="pointcut" expression="execution(* com.mount.service.UserServiceImpl.*(..))"/>
    <!--      執(zhí)行環(huán)繞增強(qiáng)  -->
    <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
  </aop:config>
</beans>

編寫(xiě)執(zhí)行前后日志

// 執(zhí)行前  實(shí)現(xiàn)spring內(nèi)置接口MethodBeforeAdvice
public class log implements MethodBeforeAdvice {
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"執(zhí)行了"+method.getName()+"方法");
    }
}
// 執(zhí)行后 實(shí)現(xiàn)AfterReturningAdvice 
public class AfterLog implements AfterReturningAdvice {
  public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    System.out.println(target.getClass().getName()+"調(diào)用了"+method.getName()+"方法"+"返回的結(jié)果為"+returnValue);
  }
}

測(cè)試:

@Test
public void test01(){
  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  UserService bean = context.getBean("userServiceImpl", UserService.class);
  bean.insert();
}

實(shí)現(xiàn)aop方式二

使用自定義類,只需要在applicationContext.xml中重新配置aop,并且自己diy一個(gè)類即可,在配置時(shí)可以選擇任一方法為前置日志或后置日志即可

<!--  配置AOP 方式二  -->
<bean id="diy" class="com.mount.diyLog.diyLogImpl"/>
<aop:config>
  <!--     自定義切面 ref引入的類   -->
  <aop:aspect ref="diy">
    <aop:pointcut id="pointcut" expression="execution(* com.mount.service.UserServiceImpl.*(..))"/>
    <aop:before method="before" pointcut-ref="pointcut"/>
    <aop:after method="after" pointcut-ref="pointcut"/>
  </aop:aspect>
</aop:config>

diylog類

public class diyLog {
  public void before(){
    System.out.println("===before方法執(zhí)行===");
  }
  public void after(){
    System.out.println("===after方法執(zhí)行===");
  }
}

注解實(shí)現(xiàn)aop

首先需要在applicationContext.xml文件中打開(kāi)SpringAOP對(duì)注解的支持

<!-- SpringAop開(kāi)啟注解支持 -->
<aop:aspectj-autoproxy/>
<!-- 映射自定義注解實(shí)現(xiàn)log類 -->
<bean id="annoLog" class="com.mount.annoLog.annoLogImpl"/>

annoLog

// Aspect標(biāo)注該類是一個(gè)切面
@Aspect
public class annoLogImpl {
  // 前置增強(qiáng)
  @Before("execution(* com.mount.service.UserServiceImpl.*(..))")
  public void before(){
    System.out.println("---方法執(zhí)行前---");
  }
  // 后置增強(qiáng)
  @After("execution(* com.mount.service.UserServiceImpl.*(..))")
  public void after(){
    System.out.println("---方法執(zhí)行后---");
  }
  // 環(huán)繞增強(qiáng)
  @Around("execution(* com.yuqu.dao.UserMapperImpl.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("環(huán)繞前");
        Object proceed = pjp.proceed();
        System.out.println("環(huán)繞后");
        System.out.println("執(zhí)行信息:"+pjp.getSignature());
        return proceed;
    }
}

最終打印:

環(huán)繞前
---方法執(zhí)行前---
刪除成功!
---方法執(zhí)行后---
方法簽名Integer com.mount.service.UserService.delete()
方法執(zhí)行返回=1
環(huán)繞后

注意around環(huán)繞增強(qiáng),如果我們執(zhí)行的sql中是有返回值的話,那么必須顯式的將pjp.proceed();返回回去,否則在調(diào)用處將會(huì)無(wú)法獲取到結(jié)果集,報(bào)空指針異常

可以發(fā)現(xiàn),around環(huán)繞增強(qiáng)首先執(zhí)行,在執(zhí)行到joinPoint.proceed()時(shí),會(huì)執(zhí)行對(duì)應(yīng)方法,執(zhí)行對(duì)應(yīng)方法的時(shí)候才會(huì)執(zhí)行前置或后置的其他增強(qiáng)操作

以上就是“Spring AOP的概念與實(shí)現(xiàn)過(guò)程是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI