这篇文章主要为大家展示了“SpringBoot使用AOP和内部方法失效怎么办”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“SpringBoot使用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和内部方法失效怎么办”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。