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

當(dāng)心!SpringBoot在這幾種情況下將導(dǎo)致代理失效

開發(fā) 前端
Pointcut定義了哪些方法會(huì)被增強(qiáng),而切點(diǎn)通常通過表達(dá)式來定義,這些表達(dá)式可以基于方法名、參數(shù)類型、注解等多種條件。

環(huán)境:SpringBoot2.7.18

1. 簡介

Spring AOP(面向切面編程)是Spring框架的核心特性之一,它以一種非侵入式的方式增強(qiáng)了應(yīng)用程序的模塊性和可維護(hù)性。通過AOP,開發(fā)者能夠?qū)M切關(guān)注點(diǎn)(如日志記錄、事務(wù)管理、安全控制等)從業(yè)務(wù)邏輯中分離出來,形成獨(dú)立的切面,從而實(shí)現(xiàn)了關(guān)注點(diǎn)的模塊化。這種分離不僅簡化了代碼結(jié)構(gòu),還提高了代碼的重用性和靈活性。Spring AOP利用代理機(jī)制在運(yùn)行時(shí)動(dòng)態(tài)地將切面織入到目標(biāo)對象中,無需修改原有代碼,極大降低了系統(tǒng)間的耦合度。

實(shí)現(xiàn)代理的核心元素

  • 切入點(diǎn)

Pointcut定義了哪些方法會(huì)被增強(qiáng),而切點(diǎn)通常通過表達(dá)式來定義,這些表達(dá)式可以基于方法名、參數(shù)類型、注解等多種條件。

  • 通知類

通知?jiǎng)t是你需要增強(qiáng)的邏輯,這其中包括了前置通知(Before Advice)、后置通知(After Advice)、環(huán)繞通知(Around Advice)、異常通知(Throws Advice)和引介通知(Introduction Advice)。

  • 處理器

有了上面2個(gè)關(guān)鍵元素后,那如何才能創(chuàng)建代理呢?這時(shí)候的BeanPostProcessor就是最為關(guān)鍵的類了,它會(huì)根據(jù)切入點(diǎn)來判斷你當(dāng)前的bean是否符合條件,對于符合條件的則進(jìn)行代理的創(chuàng)建最終返回給Spring容器。Spring容器中保存的是代理對象。而在Spring中我們最常見的幾種注冊處理器的方式是:通過下面3個(gè)注解

@Configuration
// 開啟事務(wù)(針對的事務(wù)注解@Transactional)
@EnableTransactionManagement
// 開啟AOP代理(只要具備上面的1,2條件即可)
@EnableAspectJAutoProxy
// 開啟異步支持(針對的是@Async注解)
@EnableAsync
public class AppConfig {}

具備了上面3個(gè)核心元素后,是否就一定能為bean對象創(chuàng)建代理呢?這將是接下來要介紹的內(nèi)容。

2. 不創(chuàng)建代理情況

2.1 環(huán)境準(zhǔn)備

先準(zhǔn)備基礎(chǔ)環(huán)境進(jìn)行接下來的測試使用

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

將圍繞該Service創(chuàng)建代理

@Component
@Aspect
public class LogAspect {
  @Pointcut("execution(* com.pack..*.*(..))")
  private void log() {
  }
  @Before("log()")
  public void recordLog() {
    System.out.println("before log...") ;
  }
}

該切面定義了一個(gè)前置通知,切入點(diǎn)匹配com.pack包及其子包下的所有方法。

2.2 正常創(chuàng)建代理

到此,以上定義沒有任何特殊的程序能正常的創(chuàng)建代理,如下示例:

ConfigurableApplicationContext context = SpringApplication.run(App.class, args) ;
Service service = context.getBean(Service.class);
System.out.println(service.getClass()) ;
service.save();

輸出結(jié)果

class com.pack.Service$$SpringCGLIB$$0
before log...
Service save ...

正常通過cglib創(chuàng)建代理對象。

2.3 不創(chuàng)建代理

  • Service實(shí)現(xiàn)Advice接口
public class Service implements Advice {}

再次運(yùn)行后,輸出結(jié)果

class com.pack.Service
Service save...

沒有創(chuàng)建代理,沒有執(zhí)行通知方法。

  • Service實(shí)現(xiàn)Pointcut接口
public class Service implements Pointcut {


  // 該接口需要實(shí)現(xiàn)下面2個(gè)方法
  // 這里無所謂,默認(rèn)實(shí)現(xiàn)即可
  public ClassFilter getClassFilter() {
    return null;
  }
  public MethodMatcher getMethodMatcher() {
    return null;
  }
}

輸出結(jié)果:

class com.pack.Service
Service save...

同樣,沒有創(chuàng)建代理:

  • Service實(shí)現(xiàn)AopInfrastructureBean接口
public class Service implements AopInfrastructureBean {}

該接口沒有任何方法標(biāo)記接口基礎(chǔ)設(shè)施類,輸出結(jié)果

class com.pack.Service
Service save...

沒有創(chuàng)建代理

  • Service實(shí)現(xiàn)Advisor接口

Spring創(chuàng)建代理對象,底層實(shí)現(xiàn)即使你通過注解@Aspect方式聲明的切面都會(huì)將其轉(zhuǎn)換為Advisor這種低級切面。

Advisor接口只有一個(gè)抽象方法。

public class Service implements Advisor {
  // 空實(shí)現(xiàn)即可
  public Advice getAdvice() {
    return null ;
  }
}

輸出結(jié)果與上面一樣,同樣不會(huì)創(chuàng)建代理。

  • 特殊的beanName

給Service一個(gè)特殊的beanName。

@Component("com.pack.Service.ORIGINAL")
public class Service {}

這個(gè)beanName以當(dāng)前的完整包名+類名+.ORIGINAL命名,輸出結(jié)果:

class com.pack.Service
Service save...

沒有創(chuàng)建代理,修改beanName:

@Component("xxxooo.ORIGINAL")

當(dāng)修改成上面的名稱后,再次運(yùn)行:

class com.pack.Service$$SpringCGLIB$$0
before log...
Service save ...

被代理了,這說明beanName只有是"完整包名+類名+.ORIGINAL"才不會(huì)創(chuàng)建代理對象。

  • 特殊的Advisor

該情況非常特殊也比較復(fù)雜,直接上代碼:

@Component
public class LogAdvisor extends AspectJPointcutAdvisor {


  public LogAdvisor(AbstractAspectJAdvice advice) {
    super(advice);
  }
  @Override
  public String getAspectName() {
    return "service" ;
  }
}

只要上面getAspectName方法返回值與對應(yīng)Service的beanName一致也將不會(huì)創(chuàng)建代理。

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

2021-04-15 08:01:27

Spring聲明式事務(wù)

2024-11-29 11:01:25

2020-12-08 09:45:07

MySQL數(shù)據(jù)庫索引

2022-06-27 07:23:44

MySQL常量優(yōu)化

2022-09-14 19:50:22

事務(wù)場景流程

2023-11-23 23:52:06

options請求瀏覽器

2017-12-05 13:25:40

PHP開發(fā)服務(wù)器內(nèi)存

2013-09-12 10:41:39

VDI部署

2009-12-09 10:41:26

配置靜態(tài)路由

2023-03-27 13:00:13

Javascript前端

2019-07-26 11:51:20

云計(jì)算IT系統(tǒng)

2023-08-10 17:23:39

2020-04-02 11:16:28

Linux進(jìn)程高并發(fā)

2010-04-25 17:34:30

負(fù)載均衡實(shí)現(xiàn)

2010-10-22 17:26:55

SQL Server刪

2022-08-24 15:08:19

模型數(shù)據(jù)技術(shù)

2022-09-05 10:01:19

VueReact

2015-06-01 06:39:18

JavaJava比C++

2010-07-30 15:32:23

2020-11-18 09:26:52

@property裝飾器代碼
點(diǎn)贊
收藏

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