Spring?AOP對(duì)嵌套方法不起作用的解決
Spring AOP對(duì)嵌套方法不起作用
今天在調(diào)研系統(tǒng)操作記錄日志時(shí),好多教程都是借助于Spring AOP機(jī)制來實(shí)現(xiàn)。于是也采用這種方法來實(shí)現(xiàn)。在Service中的刪除日志方法上注解自定義的切點(diǎn),但是執(zhí)行沒有生效。
代碼如下:
//嘗試刪除溢出日志
? ? public synchronized void tryDelOverflowLog() {
? ? ? ? logNum++;
? ? ? ? if (logNum - LogConst.MAX_NUM > 0) {
? ? ? ? ? ? int delNum = logNum - LogConst.MAX_NUM + LogConst.EXTRA_NUM;
? ? ? ? ? ? logNum -= delNum;
? ? ? ? ? ? removeOverflowLog(delNum);
? ? ? ? }
? ? }
?
? ? //日志溢出后,刪除最新入庫的日志
? ? @ServiceLog(type = LogConst.TYPE_LOG_RECORD, description = "操作日志緩存區(qū)溢出,系統(tǒng)自動(dòng)清空緩存區(qū)")
? ? public void removeOverflowLog(int delNum) {
? ? ? ? custLogMapper.removeOverflowLog(delNum);
? ? }在使用 Spring AOP 的時(shí)候,我們從 IOC 容器中獲取的 Service Bean 對(duì)象其實(shí)都是代理對(duì)象,而不是那些 Service Bean 對(duì)象本身,也就是說獲取的并不是被代理對(duì)象或代理目標(biāo)。當(dāng)我在自己的 Service 類中使用 this 關(guān)鍵字嵌套調(diào)用同類中的其他方法時(shí),由于 this 關(guān)鍵字引用的并不是該 Service Bean 對(duì)象的代理對(duì)象,而是其本身,故 Spring AOP 是不能攔截到這些被嵌套調(diào)用的方法的。
要解決這個(gè)問題
最簡單的方法是把自身注入到自身,用注入的這個(gè)自身去調(diào)用本方法。或者你也可以不用spring aop而是用aspectj weaving,倒是可以測底的解決該問題。我采用的是把自身注入到自身中。
? ? /**
? ? ?* 通過注入自身解決,Spring AOP嵌套調(diào)用不生效的問題
? ? ?*/
? ? @Autowired
? ? private ApplicationContext applicationContext;
? ? private LogService self;
? ? @PostConstruct
? ? private void init() {
? ? ? ? self = (LogService) applicationContext.getBean("logService");
? ? }
? ?//嘗試刪除溢出日志
? ? public synchronized void tryDelOverflowLog() {
? ? ? ? logNum++;
? ? ? ? if (logNum - LogConst.MAX_NUM > 0) {
? ? ? ? ? ? int delNum = logNum - LogConst.MAX_NUM + LogConst.EXTRA_NUM;
? ? ? ? ? ? logNum -= delNum;
? ? ? ? ? ? self.removeOverflowLog(delNum);
? ? ? ? }
? ? }Spring AOP、嵌套調(diào)用失效及解決
加入注解
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
獲取當(dāng)前代理的接口
public interface ICurrentAopProxyService<T> {
? ? default T getCurrentProxyService() {
? ? ? ? return (T) AopContext.currentProxy();
? ? }
}需要嵌套調(diào)用的Service實(shí)現(xiàn)它

調(diào)用的時(shí)候改寫代碼
public SysMerchantVersion selectByMerchantId(Long merchantId) {
return getCurrentProxyService().getOne(new QueryWrapper<SysMerchantVersion>()
.lambda()
.eq(SysMerchantVersion::getMerchantId, merchantId));
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot 創(chuàng)建對(duì)象常見的幾種方式小結(jié)
Spring Boot中創(chuàng)建對(duì)象的幾種常見方式包括使用@Component、@Service、@Repository或@Controller注解,本文就來詳細(xì)的介紹一下,感興趣的可以了解一下2024-11-11
java實(shí)現(xiàn)哈夫曼壓縮的實(shí)例
這篇文章主要介紹了java實(shí)現(xiàn)哈夫曼壓縮的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-07-07
Java?I/O?(Input/Output)文件字節(jié)流舉例詳解
Java的輸入輸出流(IO)是用于與外部設(shè)備(如文件、網(wǎng)絡(luò)連接等)進(jìn)行數(shù)據(jù)交互的機(jī)制,下面這篇文章主要給大家介紹了關(guān)于Java?I/O?(Input/Output)文件字節(jié)流的相關(guān)資料,需要的朋友可以參考下2024-08-08
java創(chuàng)建jar包并被項(xiàng)目引用步驟詳解
這篇文章主要介紹了java創(chuàng)建jar包并被項(xiàng)目引用步驟詳解,jar包實(shí)現(xiàn)了特定功能的,java字節(jié)碼文件的壓縮包,更多相關(guān)內(nèi)容需要的朋友可以參考一下2022-07-07
SpringSecurity中PasswordEncoder的使用
密碼存儲(chǔ)和加密是非常重要的,本文主要介紹了SpringSecurity中PasswordEncoder的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01

