您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“SpringBoot使用AOP和內(nèi)部方法失效怎么辦”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“SpringBoot使用AOP和內(nèi)部方法失效怎么辦”這篇文章吧。
最近在使用AOP的時(shí)候,發(fā)現(xiàn)一個(gè)問題,普通的方法AOP就能夠有用,而內(nèi)部調(diào)用的方法AOP就會(huì)失效,下面重現(xiàn)下問題
@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í)行該方法
@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)用的就生效了。在說原因前,我們先說說動(dòng)態(tài)代理 因?yàn)锳OP的原理就是動(dòng)態(tài)代理
動(dòng)態(tài)代理簡單來說就是在程序運(yùn)行的過程中,自動(dòng)生成一個(gè)指定的代理類,然后執(zhí)行程序,這個(gè)代理類可以在破壞原來被代理對象的情況下做一下額外的工作。
//接口 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é)果:
可以看到動(dòng)態(tài)代理中,內(nèi)部方法調(diào)用也是沒有生效,通過對代理類的Class文件分析,我們可以知道只有通過代理類的實(shí)例執(zhí)行的方法才會(huì)進(jìn)入到攔截處理中
而動(dòng)態(tài)代理的方法真實(shí)調(diào)用,會(huì)使用真實(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)用的方法也生效了
以上是“SpringBoot使用AOP和內(nèi)部方法失效怎么辦”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。