kimlunarove 2014-05-16
困扰了两天的Spring Aop+log4j动态日志Demo.
实现的功能:SSH框架,对Action/Service/Dao 三层的方法使用Spring Aop进行日志的添加(排除Action内的set get方法等)
遇到的问题:
Action层使用Spring Aop添加日志后,竟然获取不到前台提交的参数(就是这个问题困扰了太久,其它很 简单,service dao层的方法 都能正常)
问题解决方案以及注意事项
1).将Aop配置为 proxy-target-class="true"(基于类的代理)
2).若设置 proxy-target-class="true",需要导入cglib相关包, 但不要导入cglib jar包,而应该使用cglib-nodep jar包, 譬如我用的是 cglib-nodep-2.2.3.jar. 用cglib jar包,会报异常: Initialization of bean failed; nested exception is java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.<init>(Z)V
3).Struts2的action 需交给Spring容器去管理
相关的代码
1.Log类
package com.miao.log; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class MyLog { Logger logger = Logger.getLogger(MyLog.class); String logStr = null ; /** * 前置通知:在某连接点之前执行的通知,但这个通知不能阻止连接点前的执行 */ public void doBefore(JoinPoint jp) { logStr = jp.getTarget().getClass().getName() + " 类的 " + jp.getSignature().getName()+" 方法开始执行 ***Start***"; logger.info(logStr); } /** * 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行 */ public Object doAround(ProceedingJoinPoint pjp) throws Throwable { Object result=null; try{ result = pjp.proceed(); }catch(Exception e){ logStr = "方法:"+pjp.getTarget().getClass() + "." + pjp.getSignature().getName()+ "() "; logStr = logStr+"错误信息如下:["+e+"]"; logger.info(logStr); } return result; } /** * 后置通知 */ public void doAfter(JoinPoint jp) { logStr =jp.getTarget().getClass().getName() + " 类的 " + jp.getSignature().getName() +" 方法执行结束 ***End***"; logger.info(logStr); } }
2.Spring Aop日志相关配置
<!-- 配置日志 使用Aop 记录日志 注意: 1). 此处proxy-target-class="true" 否则Action内的参数会被拦截掉,导致action内无法获得前台传递的参数 2). Action需交给spring容器去管理 --> <aop:config expose-proxy="true" proxy-target-class="true"> <aop:aspect id="aopRiZhiAspect" ref="myRiZhi"> <!-- 对哪些方法进行日志记录, 此处屏蔽action内的set get方法 --> <aop:pointcut id="aopRiZhi" expression="(execution(* com.miao.*.*.*.*(..)) ) and (!execution(* com.miao.*.action.*.set*(..)) ) and (!execution(* com.miao.*.action.*.get*(..)) )" /> <aop:before pointcut-ref="aopRiZhi" method="doBefore"/> <aop:after pointcut-ref="aopRiZhi" method="doAfter"/> <aop:around pointcut-ref="aopRiZhi" method="doAround"/> </aop:aspect> </aop:config> <beans> <bean id="myRiZhi" class="com.miao.log.MyLog"></bean> <!-- Aop日志类 --> <bean id="logonAction" class="com.miao.logon.action.LogonAction" scope="prototype" ></bean> <!-- 要使用spring aop记录日志的action 需要交给spring容器来管理 --> </beans>
3.log4j配置, Struts配置等略, 注意需要的jar包即可,附件是去掉jar包后的项目