Spring AOP 实现拦截Controller中的方法

因为Spring的Bean扫描和Spring-MVC的Bean扫描是分开的, 两者的Bean位于两个不同的Application, 而且Spring-MVC的Bean扫描要早于Spring的Bean扫描, 所以当Controller Bean生成完成后, 再执行Spring的Bean扫描,Spring会发现要被AOP代理的Controller Bean已经在容器中存在, 配置AOP就无效了。
同样这样的情况也存在于数据库事务中, 如果Service的Bean扫描配置在spring-mvc.xml中, 而数据库事务管理器配置在application.xml中, 会导致数据库事务失效, 原理一样。
所以这里 ,我们需要把AOP放置在Controller扫描配置的文件中。

Spring的配置文件application.xml 配置如下:
<context:component-scan base-package="cn.test.demo.dao" />
<context:component-scan base-package="cn.test.demo.service" />
Spring MVC的配置文件spring-mvc.xml

<context:component-scan base-package="cn.test.demo.controller" />
<context:component-scan base-package="cn.test.demo.aspect" />

<aop:aspectj-autoproxy>aop:aspectj-autoproxy>

@Aspect
@Component
public class LoggingAspect
{
protected final org.slf4j.Logger log = LoggerFactory.getLogger(this.getClass());

/**
* 配置切入的包名
*/
@Pointcut("execution(* cn.test.demo.controller..*Controller*.*(..))")
public void controllerMethod()
{

}

@Around("controllerMethod()")
   public Object aroundControllerAdvice(ProceedingJoinPoint joinPoint)
{
try
{
return joinPoint.proceed();
} catch (Throwable throwable)
{
throwable.printStackTrace();
}finally
{
try {
Signature signature = joinPoint.getSignature();
if (signature != null) {
String clazzName = signature.getDeclaringTypeName();
String method = signature.getName();
log.info(clazzName,method);
}
} catch (Exception e) {
log.error("aroundControllerAdvice", e);
}
}
return null;
}

@AfterThrowing(value = "controllerMethod()", throwing = "exception")
public void afterThrowing(JoinPoint joinPoint, Exception exception){
Signature signature = joinPoint.getSignature();
if (signature != null)
{
String clazzName = signature.getDeclaringTypeName();
String method = signature.getName();
String param = methodParams(joinPoint, signature);
log.error("{}.{}.({})",clazzName,method,param,exception);
}
}

private String methodParams(JoinPoint pjp, Signature signature) {
StringBuffer sb = new StringBuffer();
try {
CodeSignature cs = (CodeSignature) signature;
String[] paramNames = cs.getParameterNames();
Object[] paramValues = pjp.getArgs();

for (int i = 0; i < paramNames.length; i++) {
sb.append(paramNames[i]).append("=").append(toStr(paramValues[i]));
if (i < paramNames.length - 1) {
sb.append(", ");
}
}
} catch (Exception e) {
log.error("error when generate method param info", e);
}
return sb.toString();
}

private String toStr(Object o) {
if (o == null)
{
return "nil";
}
return o.toString();
}


}

你可能感兴趣的:(spring)