先说一下情况:小弟现正用Spring AOP实现日志记录功能,上面交待Web层,Service层,Dao层都要记录,所以打算在Web层只记一下用户请求的情况,也就是说用户请求哪个Action时,记录一下操作步骤,Service层记录方法调用时的参数及返回值以及异常情况,Dao层上面交待要记录最终SQL(这个小弟现在还不知道怎么实现)。
在此只说一下Web层的日志记录,其它的略过了。我是这样的,先定义一个名为ActionName的annotation,有一个value属性,这个value属性的值就表示该Action方法的功能说明。然后我定义一个Pointcut匹配该annotation。到这里一切都没问题,能正常拦截并代理Action方法,但是前提是必须使用CGLIB!
我记得好像Spring能自动地判断目标方法并决定是使用动态代理还是CGLIB代理实现的。但是我在配置文件中如果不强制使用CGLIB代理则程序运行报错呢?
下面是我的代码:LogHandler类
package com.delver.bms.log.util;import java.lang.reflect.Method;
import java.sql.Timestamp;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;import com.delver.bms.exception.BusinessException;
import com.delver.bms.log.annotation.ActionName;
import com.delver.bms.log.annotation.TaskScheduling;
import com.delver.bms.log.dao.IAppLogDao;
import com.delver.bms.log.to.AppLog;
import com.delver.bms.util.AutoID32;
import com.delver.bms.util.TenantUtil;
import com.ibm.crl.mmt.datamodel.MTUtilFactory;
import com.ibm.crl.mmt.exception.MTException;/**
 * 日志记录切面类
 * 
 * @author yue.ch
 * 
 */
@Aspect
public class LogHandler { private IAppLogDao appLogDao; public void setAppLogDao(IAppLogDao appLogDao) {
this.appLogDao = appLogDao;
} /**
 * 定义切入点,匹配使用@ActionName注解的方法
 * @param actionName @ActionName注解value值(功能解释)
 */
@Pointcut("@annotation(actionName)")
public void annotationMethod(ActionName actionName) {
}

/**
 * 定义切入点,匹配使用@TaskScheduling注解的方法
 * @param taskScheduling @TashScheduling注解value值(功能解释)
 */
@Pointcut("@annotation(taskScheduling)")
public void annotationTaskMethod(TaskScheduling taskScheduling) {
} /**
 * 定义切入点,匹配Service层方法
 */
@Pointcut("execution(* com.delver.bms.*.service.*.*(..))")
public void serviceMethod() {
}

/**
 * 定义切入点,排除UserDetailsServiceImpl类
 */
@Pointcut("!within(com.delver.bms.identity.service.UserDetailsServiceImpl)")
public void identityServiceMethod(){}

/**
 * 定义切入点,排除日志记录功能模块的Service层方法
 */
@Pointcut("!execution(* com.delver.bms.log.service.*.*(..))")
public void logServiceMethod(){}

/**
 * 定义切入点,排除日志记录功能模块的Dao层方法
 */
@Pointcut("!execution(* com.delver.bms.log.dao.*.*(..))")
public void logDaoMethod(){} /**
 * 定义切入点,匹配Dao层方法
 */
@Pointcut("execution(* com.delver.bms.*.dao.*.*(..))")
public void daoMethod(){}



/**
 * 系统任务调度方法前置通知(记录任务调度方法功能说明及执行)
 * 
 * @param joinPoint
 * @param taskScheduling
 */
@Around("annotationTaskMethod(taskScheduling)")
public void aroundTaskScheduling(ProceedingJoinPoint joinPoint,
TaskScheduling taskScheduling) throws Throwable { System.out.println("ddd");
} /**
 * Action方法前置通知(记录Action方法功能说明)
 * 
 * @param joinPoint
 * @param actionName
 */
@Before("annotationMethod(actionName)")
public void beforeActionLog(JoinPoint joinPoint, ActionName actionName) { System.out.println("ddd"); } /**
 * Service方法环绕通知
 * 
 * @param joinPoint
 * @return
 */
@Around("serviceMethod() && identityServiceMethod() && logServiceMethod()")
public Object aroundServiceLog(ProceedingJoinPoint joinPoint)
throws Throwable {
System.out.println("ddd");
} /**
 * Dao方法环绕通知(记录SQL)
 * 
 * @param jointPoint
 * @return
 */
@Around("daoMethod() && logDaoMethod()")
public Object aroundDaoLog(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("ddd");
}
配置文件:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <aop:aspectj-autoproxy proxy-target-class="true"/> <bean id="appLogDao" class="com.delver.bms.log.dao.AppLogDaoiBatis">
<property name="sqlMapClient" ref="sqlMapClient" />
</bean> <bean id="appLogManager" class="com.delver.bms.log.service.AppLogManagerImpl">
<property name="appLogDao" ref="appLogDao" />
</bean> <bean id="appLogInfo" class="com.delver.bms.log.web.AppLogInfo"
scope="prototype">
<property name="appLogManager" ref="appLogManager" />
<property name="tenantManager" ref="tenantManager" />
</bean>
<!-- 系统日志处理类 -->
<bean id="appLogHandler" class="com.delver.bms.log.util.LogHandler">
<property name="appLogDao" ref="appLogDao" />
</bean></beans>异常信息:
java.lang.NoSuchMethodException: $Proxy51.visit()
at java.lang.Class.getMethod(Unknown Source)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(AnnotationValidationInterceptor.java:55)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:41)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
at com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
at com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
at com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:123)字数有限,下面略