这次需要处理的问题未,某个接口有多个实现类由多个部门共同实现(随时可增加),这些接口实现类有时会多次循环执行,在生产执行过程中有时候会报错,有时候会修改了某些数据。所以即使找到数据被修改的SQL或日志,也不好确认是哪次循环,哪个步骤修改了数据。
基于上述问题通过切面给给每个步骤的方法增加日志,以便生产出现问题,可以通过日志快速定位问题所在步骤。
下面直接上配置、上代码
<!--回历史步骤加入切面日志-->
<bean id="facadeB2HStepAop"
class="com.xQuant.platform.app.aop.aspect.FacadeB2HStepAspect"></bean>
<aop:config>
<aop:pointcut id="facadeB2HStepServiceProcess"
expression="execution(* com.xquant.platform.component.b2h.facade.FacadeB2HStepService.process(..))"/>
<!--配置事务通知-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="facadeB2HStepServiceProcess"/>
<aop:aspect ref="facadeB2HStepAop">
<aop:around pointcut-ref="facadeB2HStepServiceProcess"
arg-names="joinPoint" method="facadeB2HStepLogAspect"/>
</aop:aspect>
</aop:config>
切面配置说明
1、bean id=“facadeB2HStepAop” 定义切面类
2、expression=“execution(* com.xquant.platform.component.b2h.facade.FacadeB2HStepService.process(…))”
对FacadeB2HStepService接口下所有实现类process方法增加环绕切面
3、 <aop:advisor advice-ref=“txAdvice” pointcut-ref=“facadeB2HStepServiceProcess”/>定义切面类事物
4、aop:around 切面类型为环绕切面
5、arg-names=“joinPoint” 切面方法参数名称
6、method="facadeB2HStepLogAspect"切面处理方法
/**
*
*/
package com.xQuant.platform.app.aop.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import com.xQuant.base.utils.LogUtils;
import com.xQuant.platform.app.trade.service.TradeService;
/**回历史步骤日志切面
* @author xinglong.wang
*/
@Aspect
public class FacadeB2HStepAspect implements InitializingBean {
@Autowired
TradeService tradeService;
/**
* 回历史步骤日志拦截器日志记录方法
* @param joinPoint
* @throws Throwable
*/
public void facadeB2HStepLogAspect(ProceedingJoinPoint joinPoint) throws Throwable{
try {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
String beforeStr = "回历史步骤日志拦截器" +joinPoint.getTarget().getClass().getName()+" 开始:";
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
beforeStr = beforeStr+ " 参数"+i+":"+ joinPoint.getArgs()[i].toString() + " ";
}
//String sysordid = joinPoint.getArgs()[0].toString();
LogUtils.debug(this.getClass(), beforeStr);
//用改变后的参数执行目标方法,此处参数不变
joinPoint.proceed(args);
LogUtils.debug(this.getClass(),"回历史步骤日志拦截器" +joinPoint.getTarget().getClass().getName()+" 结束");
} catch (Exception e) {
LogUtils.error(this.getClass(), "回历史拦截器异常,请检查");
}
}
@Override
public void afterPropertiesSet() throws Exception {
}
}
切面类实现说明
1、切面处理方法facadeB2HStepLogAspect
2、获取被切入的实体类类名 joinPoint.getTarget().getClass().getName()
3、获取被切入方法的参数Array
4、 方法执行前,日志中记录被切入的类,被切入方法的参数(由于接口中只有一个方法,所以这里没有记录方法,如想获取方法可以参考下一点)
LogUtils.debug(this.getClass(), beforeStr);
//用改变后的参数执行目标方法,此处参数不变。
调用此方法后开始执行被切入的方法
joinPoint.proceed(args);
方法执行后日志
LogUtils.debug(this.getClass(),“回历史步骤日志拦截器”
5、一些其他切面可以用到的数据
System.out.println(“classname:” + targetMethod.getDeclaringClass().getName());
System.out.println(“superclass:” + targetMethod.getDeclaringClass().getSuperclass().getName());
System.out.println(“isinterface:” + targetMethod.getDeclaringClass().isInterface());
System.out.println(“target:” + pjp.getTarget().getClass().getName());
System.out.println(“proxy:” + pjp.getThis().getClass().getName());
System.out.println(“method:” + targetMethod.getName());
AOP的一些其他扩展
上面的案例只是最基础的利用AOP加日志。除此之外可以用于调用方法前预处理参数、调用方法后的额外处理,主要针对一些不太好操作的(比如上面接口及实现方式都是其他部门的代码或者一些其他的开源的jar包中代码)或者需要系统统一处理的问题(比如系统级别的日志)。