【踩坑】基于注解的AOP失效。内部方法使用this调用方式时,导致AOP生效的问题

今天在把定时模块(job)抽离出来做成通用的starter时,遇到了基于注解的AOP失效的问题,在此分享给大家。

描述
通过AOP实现的定时任务的重试策略,定义了一个注解@Retry。在项目中使用@Retry标记的方法,在执行时会被切入,并且通过重试模板进行放行。
在这里插入图片描述

问题
job分为单例和集群两种执行方式,单例的@Retry正常生效,但是集群的@Retry不生效,下面是单例和集群的伪代码

单例:
    @Retry
    @Override
    public Boolean execute(ScheduleTaskDto task) {
           /**
	       * 保证原子性策略...
		   */
		   return job.invoke(task); 
		   /**
	       * 保证原子性策略...
		   */
    }
集群:
    @Override
    public Boolean execute(ScheduleTaskDto task) {
       /**
       * 分布式执行策略...
	   */
	   this.doExecute(task);
       /**
       * 分布式执行策略...
	   */
    }
    
    @Retry
    public boolean doExecute(ScheduleTaskDto task) {
          /**
	       * 保证原子性策略...
		   */
		   return job.invoke(task); 
		   /**
	       * 保证原子性策略...
		   */
    }

通过上述的代码我们可以发现,集群模式的@Retry属于类的内部方法的调用,在spring中AOP是通过代理对象来实现,而在springboot中,内部方法的调用时通过实例对象来调用的,这也就意味着内部方法的@Retry不会被代理到。

解决思路
分析出问题的所在后,我就大概知道应该怎么修改的了。

  • 方案一:通过 @EnableAspectJAutoProxy(exposeProxy=true) 加(XX)AopContext.currentProxy()) 来实现内部方法的AOP代理的。
  • 方案二:通过 @Lazy @Autowired [当前类] 加 [当前类].[内部方法] 来实现内部方法的AOP代理的。
  • 方案三:通过上下文中的Bean来执行内部方法。

方案一是不适合在自定义的starter进行使用的,其实 @EnableAspectJAutoProxy是@Import的高级注解,熟悉springboot启动流程的朋友应该知道是在主启动类的run方法中进行解析的,所在对应自定义的starter,是不生效的。我是使用的方案二(方案三也可以),如下:

public class ClusterExecutor implements Executor {
	@Lazy
    @Autowired
    private ClusterExecutor clusterExecutor;
    
    @Override
    public Boolean execute(ScheduleTaskDto task) {
       /**
       * 分布式执行策略...
	   */
	   clusterExecutor.doExecute(task);
       /**
       * 分布式执行策略...
	   */
    }
    
    @Retry
    public boolean doExecute(ScheduleTaskDto task) {
          /**
	       * 保证原子性策略...
		   */
		   return job.invoke(task); 
		   /**
	       * 保证原子性策略...
		   */
    }
}

我们不难发现,上述的三个方案,其实都是想办法让原本的内部方法调用改为通过上下文对象进行直接调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值