欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot使用AOP,內(nèi)部方法失效的解決方案

 更新時(shí)間:2021年08月28日 14:46:27   作者:Lpepsi  
這篇文章主要介紹了SpringBoot使用AOP,內(nèi)部方法失效的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

SpringBoot使用AOP,內(nèi)部方法失效

最近在使用AOP的時(shí)候,發(fā)現(xiàn)一個(gè)問題,普通的方法AOP就能夠有用,而內(nèi)部調(diào)用的方法AOP就會失效,下面重現(xiàn)下問題

AOP切面

@Aspect
@Component
public class AuthorityAspect {
    @Pointcut("execution(* authority.service.AuthorityService.getExecutableSql(..))")
    private void pointCut() {}
    @Around(value = "pointCut()")
    public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        String sql = (String) args[1];
        args[1] = sql + " AOP ";
        return joinPoint.proceed(args);
    }

該切面的作用就是,當(dāng)執(zhí)行g(shù)etExecutableSql()方法,織入切面,獲取到該方法的參數(shù),修改參數(shù)然后再執(zhí)行該方法

現(xiàn)在有兩個(gè)方法

@Service
public class AuthorityService {
    public String getExecutableSql(String dataSourceId, String sql, Object page){
        return sql;
    }
    public String getInner(String dataSourceId, String sql, Object page){
        String str = this.getExecutableSql(dataSourceId, sql, page);
        return str;
    }
}
  • 一個(gè)是普通方法getExecutableSql(),
  • 一個(gè)是在內(nèi)部調(diào)用了getExecutableSql()的getInner()方法

同時(shí)運(yùn)行這兩個(gè)方法

在這里插入圖片描述

可以發(fā)現(xiàn)內(nèi)部調(diào)用了getExecutableSql()的方法,AOP對它并沒有生效,直接調(diào)用的就生效了。在說原因前,我們先說說動態(tài)代理 因?yàn)锳OP的原理就是動態(tài)代理

動態(tài)代理簡單來說就是在程序運(yùn)行的過程中,自動生成一個(gè)指定的代理類,然后執(zhí)行程序,這個(gè)代理類可以在破壞原來被代理對象的情況下做一下額外的工作。

寫一個(gè)簡單的動態(tài)代理的例子

//接口
public interface ProxyService {
    void save();
    void email();
    void register();
}
//實(shí)現(xiàn)類
@Service
public class ProxyServiceImpl implements ProxyService{
    @Override
    public void save() {
    }
    @Override
    public void email() {
    }
    @Override
    public void register() {
        this.save();
        this.email();
    }
}
//獲得代理
public class ServiceProxy {
    public static Object getProxy(Class<?> clazz,Object target){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object invoke = method.invoke(target, args);
                System.out.println("after method: "+method.getName());
                return invoke;
            }
        });
    }
}
//測試類
public class ProxyTest {
    public static void main(String[] args) {
        ProxyService proxyService = (ProxyService) ServiceProxy.getProxy(ProxyService.class, new ProxyServiceImpl());
        proxyService.register();
    }
}

結(jié)果:

在這里插入圖片描述

可以看到動態(tài)代理中,內(nèi)部方法調(diào)用也是沒有生效,通過對代理類的Class文件分析,我們可以知道只有通過代理類的實(shí)例執(zhí)行的方法才會進(jìn)入到攔截處理中

在這里插入圖片描述

而動態(tài)代理的方法真實(shí)調(diào)用,會使用真實(shí)被代理對象實(shí)例進(jìn)行方法調(diào)用,故在實(shí)例方法中通過this獲取的都是被代理的真實(shí)對象的實(shí)例,而不是代理對象自身。通過Debug可以看到

在這里插入圖片描述

this獲取的不是代理對象,因此無法進(jìn)入攔截處理,所以代理增強(qiáng)的方法沒有執(zhí)行。原因知道了,那就解決辦法就是讓代理對象去調(diào)用這些方法,就能夠進(jìn)入攔截處理了,修改下代碼

@Service
public class ProxyServiceImpl implements ProxyService{
    
    @Override
    public void save() {
    }
    @Override
    public void email() {
    }
    @Override
    public void register() {
        //獲取代理對象
        ProxyService proxyService = (ProxyService) ServiceProxy.getProxy(ProxyService.class, new ProxyServiceImpl());
        proxyService.save();
        proxyService.email();
    }
}

執(zhí)行一下

在這里插入圖片描述

在SpringBoot中可以用下面的方法,來使內(nèi)部調(diào)用的方法AOP也能對其生效

@Service
public class AuthorityService {
	//獲取代理對象
    @Autowired
    private AuthorityService authorityService;
    public String getExecutableSql(String dataSourceId, String sql, Object page){
        return sql;
    }
    public String getInner(String dataSourceId, String sql, Object page){
        String str = authorityService.getExecutableSql(dataSourceId, sql, page);
        return str;
    }
}

在這里插入圖片描述

可以看到內(nèi)部調(diào)用的方法也生效了

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入探討JAVA中的異常與錯(cuò)誤處理

    深入探討JAVA中的異常與錯(cuò)誤處理

    這篇文章詳細(xì)介紹了JAVA中的異常與錯(cuò)誤處理,有需要的朋友可以參考一下
    2013-09-09
  • 如何搭建一個(gè)完整的Java開發(fā)環(huán)境

    如何搭建一個(gè)完整的Java開發(fā)環(huán)境

    這篇文章主要教大家如何搭建一個(gè)完整的Java開發(fā)環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • SpringCloud Stream消息驅(qū)動實(shí)例詳解

    SpringCloud Stream消息驅(qū)動實(shí)例詳解

    這篇文章主要介紹了SpringCloud Stream消息驅(qū)動的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • MyBatis執(zhí)行批處理操作的實(shí)現(xiàn)示例

    MyBatis執(zhí)行批處理操作的實(shí)現(xiàn)示例

    在MyBatis中,批處理操作是一種高效執(zhí)行多條語句的方式,下面就來介紹一下MyBatis執(zhí)行批處理操作的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • idea 實(shí)現(xiàn)搜索jdk中的類和包操作

    idea 實(shí)現(xiàn)搜索jdk中的類和包操作

    這篇文章主要介紹了idea 實(shí)現(xiàn)搜索jdk中的類和包操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • java中g(shù)c算法實(shí)例用法

    java中g(shù)c算法實(shí)例用法

    在本篇文章里小編給大家整理了一篇關(guān)于java中g(shù)c算法實(shí)例用法,有興趣的朋友們可以參考學(xué)習(xí)下。
    2021-01-01
  • springboot框架各個(gè)層次基礎(chǔ)詳解

    springboot框架各個(gè)層次基礎(chǔ)詳解

    這篇文章主要介紹了springboot框架各個(gè)層次基礎(chǔ),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 使用maven的profile構(gòu)建不同環(huán)境配置的方法

    使用maven的profile構(gòu)建不同環(huán)境配置的方法

    這篇文章主要介紹了使用maven的profile構(gòu)建不同環(huán)境配置的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • java圖片壓縮工具類

    java圖片壓縮工具類

    這篇文章主要為大家詳細(xì)介紹了java圖片壓縮工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • 源碼解析springbatch的job運(yùn)行機(jī)制

    源碼解析springbatch的job運(yùn)行機(jī)制

    這篇文章主要介紹了springbatch的job是如何運(yùn)行的,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08

最新評論