我是靠谱客的博主 洁净外套,最近开发中收集的这篇文章主要介绍SpringBoot使用AOP,内部方法失效的解决方案,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

SpringBoot使用AOP,内部方法失效

最近在使用AOP的时候,发现一个问题,普通的方法AOP就能够有用,而内部调用的方法AOP就会失效,下面重现下问题

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);
    }

该切面的作用就是,当执行getExecutableSql()方法,织入切面,获取到该方法的参数,修改参数然后再执行该方法

现在有两个方法

@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;
    }
}
  • 一个是普通方法getExecutableSql(),
  • 一个是在内部调用了getExecutableSql()的getInner()方法

同时运行这两个方法

可以发现内部调用了getExecutableSql()的方法,AOP对它并没有生效,直接调用的就生效了。在说原因前,我们先说说动态代理 因为AOP的原理就是动态代理

动态代理简单来说就是在程序运行的过程中,自动生成一个指定的代理类,然后执行程序,这个代理类可以在破坏原来被代理对象的情况下做一下额外的工作。

写一个简单的动态代理的例子

//接口
public interface ProxyService {
    void save();
    void email();
    void register();
}
//实现类
@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();
    }
}

结果:

可以看到动态代理中,内部方法调用也是没有生效,通过对代理类的Class文件分析,我们可以知道只有通过代理类的实例执行的方法才会进入到拦截处理中

而动态代理的方法真实调用,会使用真实被代理对象实例进行方法调用,故在实例方法中通过this获取的都是被代理的真实对象的实例,而不是代理对象自身。通过Debug可以看到

this获取的不是代理对象,因此无法进入拦截处理,所以代理增强的方法没有执行。原因知道了,那就解决办法就是让代理对象去调用这些方法,就能够进入拦截处理了,修改下代码

@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();
    }
}

执行一下

在SpringBoot中可以用下面的方法,来使内部调用的方法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;
    }
}

可以看到内部调用的方法也生效了

以上为个人经验,希望能给大家一个参考,也希望大家多多支持靠谱客。

最后

以上就是洁净外套为你收集整理的SpringBoot使用AOP,内部方法失效的解决方案的全部内容,希望文章能够帮你解决SpringBoot使用AOP,内部方法失效的解决方案所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(82)

评论列表共有 0 条评论

立即
投稿
返回
顶部