spring aop 同类调用失效解决方案

原文链接:https://blog.csdn.net/u014365523/article/details/119849844

问题描述

在同一个类中调用添加注解的sendMessage方法,注解失效。

//this.sendMessage();      失效
purchaseCommonService.sendMessage(messageVo);
    @MessageLogAnnotation(messageContent = "您有新的交接单信息,请处理", messageType = MessageTypeConstant.PRIVATE_MESSAGE_TYPE, businessURL = "", messageField = "receiverId",messageFieldName ="receiver")
    public void sendMessage(MessageVo messageVo) {
        System.out.println("发送消息至" + messageVo.getReceiver());
    }

原因分析:

在这里插入图片描述
在Spring中经常使用自定义注解或是spring已经封装
好的注解,通过AOP的方式是实现代码复用,避免重复劳动。而Spring实现AOP是通过动态代理来实现的(默认有接口的情况下使用JDK的动态代理,也可以通过配置proxyTargetClass来制定使用CGLib,没有接口的情况下使用CGLib).
但是无论哪一种代理,都是在原有方法的外面包一层,通过方法外的代理层来实现AOP的逻辑。
也就是说我们首先调用的是AOP代理对象而不是目标对象。但是我们使用this.sendMessage()时,this表示的是当前对象,而不是代理对象,因此注解失效。
所以,解决代理无效的根本方法就是获取到代理对象,使用代理对象进行调用


解决方案:

1. 方法一:

	最简单的方法就是将调用的方法sendMessage()方法放在另外一个类中进行调用,而不是在一个类中同类调用,就不会出现问题了。

2. 方法二:

	从ApplicationContext中直接获取
	获取ApplicationContext有多种方法:
	方法2.1 使用AopContext.currentProxy()
public class A {
    public void serviceB() {
            ......
            //此处调用的就是代理后的方法
            ((A)AopContext.currentProxy()).serviceA();
            ......
    }
}

使用AopContext.currentProxy()注意必须在程序启动时开启EnableAspectJAutoProxy注解,设置代理暴露方式为true,如下面所示:

/**
 * EnableAspectJAutoProxy注解两个参数作用分别为:
 *
 * 一个是控制aop的具体实现方式,为true的话使用cglib,为false的话使用java的Proxy,默认为false。
 * 第二个参数控制代理的暴露方式,解决内部调用不能使用代理的场景,默认为false。
 *
 *
 */
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@SpringBootApplication
public class SpringAopApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringAopApplication.class, args);
	}
}

方法2.2 使用ApplicationContextAware
通过spring生命周期,直接将ApplicationContext注入进来
public class A implements ApplicationContextAware {
   private ApplicationContext applicationContext;
    

  @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
       this.applicationContext = applicationContext;
   }
   
   
   public void serviceB() {
           ......
           //此处调用的就是代理后的方法
           applicationContext.getBean(A.class).serviceA();
           ......
   }
}

3. 方法三:

	在实现类中注入自身,这个有点取巧。还是以上面serviceB()为例,我们如果调用this.serviceA(),this指向对象本身、不会指向代理后的对象,因此肯定不可以,但我们可以让spring提供给我们代理后的对象:
@Service
public class Child implements IChild {
    
    //通过spring将代理后对象注入到self变量
    @Autowired
    private Child child;
    
    @Override
    public Map eat() throws GendorException {
        String name = child.name();//此处调用的就是代理后的方法
        System.out.println(name);
        return null;
    }

    @SysLog
    public String name (){
        return "zhangjiguo";
    }
}
  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring AOP 失效的原因可能有很多,以下是一些可能的原因: 1. 未配置正确的切面表达式:切面表达式定义了应该在哪些方法上应用切面。如果切面表达式不正确,就无法正确地匹配到目标方法,并且切面将无法生效。 2. 目标方法没有被代理:Spring AOP 使用动态代理来实现切面,在运行时生成代理对象,并将切面应用于代理对象上的目标方法。如果目标方法没有被代理,切面将无法生效。 3. 目标方法被直接调用而不是通过代理调用:如果目标对象的方法被其他部分直接调用,而不是通过生成的代理对象调用,那么切面将无法生效。 4. 切面的顺序问题:在一个应用中可能存在多个切面,每个切面都可以定义相同或不同的切面表达式。如果切面的顺序不正确,可能会导致切面失效,例如一个切面将目标方法拦截之后,另一个切面再次拦截该方法。 5. 使用错误的切面类型:Spring AOP 支持多种类型的切面,如前置通知、后置通知、异常通知等。如果使用了错误的切面类型,或者切面类型不匹配目标方法,切面将无法生效。 6. 目标方法没有被正确地扫描到:Spring AOP 使用自动扫描来发现目标方法,并将切面应用于这些方法上。如果目标方法没有被正确地扫描到,切面将无法生效。 总结来说,Spring AOP 失效的原因可能是由于切面表达式的问题、代理问题、调用方式问题、切面顺序问题、切面类型问题、以及扫描问题。为了确保切面生效,我们需要仔细检查配置,并理解Spring AOP的工作原理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值