自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

強大!SpringBoot通過三種方式實現(xiàn)AOP切面,第三種方式性能極佳

開發(fā) 前端
動態(tài)代理靈活輕量,運行時織入;Java Agent在JVM層面攔截類加載,支持廣泛AOP場景,性能優(yōu)化潛力大但配置相對復雜;AspectJ-Maven-Plugin編譯時修改字節(jié)碼,減少運行時開銷,支持復雜邏輯但需重新編譯。?

環(huán)境:SpringBoot2.7.18

1. 簡介

Spring框架通過多種機制增強代碼功能,實現(xiàn)切面編程(AOP)。核心之一是通過動態(tài)代理技術(shù),在運行時為Bean織入(動態(tài)代理)額外功能(如日志、安全等),無需修改源代碼。此外,利用Java Agent技術(shù)(如AspectJ Weaver),可以在JVM層面攔截類加載過程,動態(tài)修改類字節(jié)碼,從而實現(xiàn)更廣泛的AOP支持。最后,AspectJ-Maven-Plugin編譯插件在編譯時直接修改源代碼或字節(jié)碼,確保切面邏輯與業(yè)務代碼無縫集成,優(yōu)化了性能并減少了運行時開銷。這些技術(shù)使得開發(fā)者能更靈活地管理橫切關(guān)注點,提升代碼模塊性和可維護性。接下來我們將詳細的介紹這3種AOP實現(xiàn)的方式。

2. 實戰(zhàn)案例

2.1 準備環(huán)境

Service類

@Service
public class UserService {
  
  public void save() {
    System.out.println("save...") ;
  }
}

接下來的所有示例都將圍繞著上面這個Service。

運行測試類

SpringApplication app = new SpringApplication(AppApplication.class) ;
app.setWebApplicationType(WebApplicationType.NONE) ;
ConfigurableApplicationContext context = app.run(args) ;
UserService us = context.getBean(UserService.class) ;
us.save() ;

啟動測試類

2.2 代理方式

該種方式,是我們工作中用的最為普遍的方式,因為該種方式靈活,無需修改代碼,適用于運行時切面增強,易于理解和集成。如下示例:

定義切面

@Component
@Aspect
public class LogAspect {
  
  @Pointcut("execution(* com.pack..*Service.*(..))")
  private void log() {}
  
  @Before("log()")
  public void before(JoinPoint jp) {
    System.out.println("before, " + jp.getSignature()) ;
  }
}

動態(tài)代理方式,只需要定義上面的切面Bean類。

運行測試代碼,輸出結(jié)果

before, void com.pack.aop.agent.UserService.save()
save...

通過動態(tài)代理方式,只需要在項目中定義@Aspect切面即可完成增強邏輯。我們將獲取的UserService Class打印如下:

圖片圖片

通過CGLIB生成了代理類。

2.3 Agent增強方式

該種方式是在JVM層面攔截,支持更廣泛的AOP場景,性能優(yōu)化潛力大(相比較于上面代理方式)。要實現(xiàn)這種方式,我們首先需要定義aop.xml文件(META-INF中)

<aspectj>
  <weaver>
    <!-- 對哪些類進行增強 -->
    <include within="com.pack.aop.agent..*" />
  </weaver>
  <!-- 定義切面類,可以定義多個 -->
  <aspects>
    <aspect name="com.pack.aop.agent.LogAspect" />
  </aspects>
</aspectj>

接下來就運行時還需要配置jvm運行時參數(shù)

-javaagent:d:/maven/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar

注:這里的版本最后根據(jù)你當前環(huán)境的版本來指定。

運行測試代碼:

圖片圖片

我們的業(yè)務代碼被增強了,同時UserService并沒有創(chuàng)建代理。通過反編譯查看UserService。

圖片圖片

編譯后的字節(jié)碼也沒有任何的變化。Agent的原理就在進行類加載時對類進行增強。

2.4 編譯插件方式

動態(tài)代理的方式,通過對目標類生成代理,在執(zhí)行目標方法前執(zhí)行增強邏輯Advice,這種方式多少對性能是有影響的。而編譯插件方式是在編譯時增強,性能最佳,深度集成,減少運行時開銷。

添加maven插件

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>1.11</version>
  <configuration>
      <complianceLevel>1.8</complianceLevel>
      <source>1.8</source>
      <target>1.8</target>
      <showWeaveInfo>true</showWeaveInfo>
    <Xlint>ignore</Xlint>
      <encoding>UTF-8</encoding>
      <skip>true</skip>
  </configuration>
  <executions>
      <execution>
          <configuration>
              <skip>false</skip>
          </configuration>
          <goals>
              <goal>compile</goal>
          </goals>
      </execution>
  </executions>
</plugin>

接下來我們可以將LogAspect類上的@Component注解刪除了,現(xiàn)在不需要了。重新編譯項目

mvn clean compile

再次運行測試代碼;

圖片圖片

我們的代碼同樣被增強了,同時打印了UserService類,該類并沒有被代理。反編譯該類。

圖片圖片

通過反編譯得知,在編譯階段就對我們的代碼進行了增強。這也是此種方式性能最佳的原因。

總結(jié):以上三種方式增強代碼:動態(tài)代理靈活輕量,運行時織入;Java Agent在JVM層面攔截類加載,支持廣泛AOP場景,性能優(yōu)化潛力大但配置相對復雜;AspectJ-Maven-Plugin編譯時修改字節(jié)碼,減少運行時開銷,支持復雜邏輯但需重新編譯。

責任編輯:武曉燕 來源: Spring全家桶實戰(zhàn)案例源碼
相關(guān)推薦

2022-05-30 07:07:35

Java監(jiān)聽文件Java 8

2014-12-31 17:42:47

LBSAndroid地圖

2021-06-24 08:52:19

單點登錄代碼前端

2021-11-05 21:33:28

Redis數(shù)據(jù)高并發(fā)

2023-06-20 12:15:46

ChatGPT人工智能責任

2010-03-12 17:52:35

Python輸入方式

2024-09-20 05:49:04

SpringBoot后端

2012-07-17 09:16:16

SpringSSH

2018-07-10 14:23:02

2010-09-07 16:31:27

CSS

2018-04-02 14:29:18

Java多線程方式

2024-07-01 12:42:58

2023-12-04 09:31:13

CSS卡片

2014-07-30 17:10:38

LVS集群負載均衡

2009-07-03 18:32:18

JSP頁面跳轉(zhuǎn)

2019-11-20 18:52:24

物聯(lián)網(wǎng)智能照明智能恒溫器

2010-06-13 16:04:14

MySQL三種安裝方式

2020-11-01 17:10:46

異步事件開發(fā)前端

2011-04-08 11:13:50

CISCO IOS令牌桶雙桶
點贊
收藏

51CTO技術(shù)棧公眾號