Spring切面AOP目标类被多次代理导致通知被多次执行

1.首先写了一个环绕通知

package com.nstc.aims.interceptor;

import java.io.PrintStream;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class EntityHistoryInterceptor
  implements MethodInterceptor
{
  public Object invoke(MethodInvocation methodInvocation)
    throws Throwable
  {
    Method method = methodInvocation.getMethod();
    System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
    System.out.println(methodInvocation.toString());
    System.out.println(Integer.toHexString(methodInvocation.hashCode()));
    System.out.println(method.getDeclaringClass());
    System.out.println(method.toString());
    System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
    String methodName = method.toGenericString();
    String xmlName = methodName.substring(methodName.lastIndexOf(" ") + 1);
    System.out.println(xmlName);
    
    Object object = methodInvocation.proceed();
    return object;
  }
}

配置文件,由于公司使用的是Spring1.2.9,配置文件没有aop标签。:

	
		
			
				AIMS.accountBasicSetService
				AIMS.accountService
				AIMS.associateBankService
				AIMS.associateBankService
				AIMS.accountBalanceService
				AIMS.accountRecordService
				AIMS.bizFlowService
				AIMS.bp3CallBackService
				AIMS.bp3ConnectService
				AIMS.commonService
				AIMS.umFormService
				AIMS.accountSynchroService
				AIMS.cfbRemoteService
				AIMS.attachService
				AIMS.recordMouldService
			
		
		
			
 				AIMS.transactionInterceptor //这个是公司原有的配置
 				AIMS.entityHistoryAdvisor //这个是我加的切面
			
		
	

执行结果如图:

Spring切面AOP目标类被多次代理导致通知被多次执行_第1张图片

原因是:

Proxy$285代理了Bean,Proxy$286代理了Proxy$285,我写的切面代理了Proxy$286,

所以导致执行了三次。

考虑是配置文件使用的spring的bean有问题,于是换了一种实现方式:

	

	
		
	
	
	
		
		
	

结果和一开始一样,也是被代理了三次,改变位置也没办法。

考虑不使用环绕通知,使用后置通知,并且把切面放到最上面试一下。如果不行的话,就要考虑在方法中判断target了。

Interceptor:

public class EntityHistoryAfterAdvice implements AfterReturningAdvice {

    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        System.out.println(target);
    }
}

配置文件

	
		
			
				AIMS.accountBasicSetService
				AIMS.accountService
				AIMS.associateBankService
				AIMS.associateBankService
				AIMS.accountBalanceService
				AIMS.accountRecordService
				AIMS.bizFlowService
				AIMS.bp3CallBackService
				AIMS.bp3ConnectService
				AIMS.commonService
				AIMS.umFormService
				AIMS.accountSynchroService
				AIMS.cfbRemoteService
				AIMS.attachService
				AIMS.recordMouldService
			
		
		
			
 				AIMS.entityHistoryAdvisor
 				AIMS.transactionInterceptor
			
		
	
	
	
    

    
        
            
        
        
        
            .*RecordMouldService.*
        
    

结果:

Spring切面AOP目标类被多次代理导致通知被多次执行_第2张图片

执行了6次,分析应该是这样的。应该执行5次,最后多的那一次是最后的代理类的顺序导致。

Spring切面AOP目标类被多次代理导致通知被多次执行_第3张图片

应当把后置通知放到最后,执行了5次。

Spring切面AOP目标类被多次代理导致通知被多次执行_第4张图片

后面考虑是实现的接口不对:

换成了Cglib的接口MethodInterception,结果直接报错。

 

代理那个类的方法在本模块没有找到,有可能是公司框架的封装。无权修改。

 

实在没办法了,只有去invoke方法中判断target了。

最终代码如下:

package com.nstc.aims.interceptor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ReflectiveMethodInvocation;

import com.nstc.aims.service.impl.RecordMouldServiceImpl;

/**
 * 

Title: EntityHistoryAroundAdvice.java

* *

Description: 环绕通知

* *

Company: 北京九恒星科技股份有限公司

* * @author luhao * * @since:2019年6月5日 上午11:59:46 * */ public class EntityHistoryAroundAdvice implements MethodInterceptor{ public Object invoke(MethodInvocation methodInvocation) throws Throwable { ReflectiveMethodInvocation reflectiveMethodInvocation = (ReflectiveMethodInvocation) methodInvocation; boolean isRealClass = reflectiveMethodInvocation.getThis().getClass() == RecordMouldServiceImpl.class; if(!isRealClass) { return methodInvocation.proceed(); } Object[] args = reflectiveMethodInvocation.getArguments();//方法参数 Object object = methodInvocation.proceed();//方法结果 return object; } }
	
		
			
				AIMS.accountBasicSetService
				AIMS.accountService
				AIMS.associateBankService
				AIMS.associateBankService
				AIMS.accountBalanceService
				AIMS.accountRecordService
				AIMS.bizFlowService
				AIMS.bp3CallBackService
				AIMS.bp3ConnectService
				AIMS.commonService
				AIMS.umFormService
				AIMS.accountSynchroService
				AIMS.cfbRemoteService
				AIMS.attachService
				AIMS.recordMouldService
			
		
		
			
 				AIMS.transactionInterceptor
 				AIMS.entityHistoryAdvisor
			
		
	
	
	
    

    
        
            
        
        
        
            .*RecordMouldService.*
        
    

 

你可能感兴趣的:(Java学习笔记)