https://www.cnblogs.com/mosmith/p/6785708.html
注解@EnableAspectJAutoProxy。从下面EnableAspectJAutoProxy的定义可以看到,注解导入了AspectJAutoProxyRegistrar配置类。
AspectJAutoProxyRegistrar主要在BeanDefinitionRegistry里面注册了AnnotationAwareAspectJAutoProxyCreator。从AnnotationAwareAspectJAutoProxyCreator的继承结构可以看出AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,类似EnableWebMvc,这个类用来整合AspectJ和Spring的IOC容器。
我们跳到继承结构上与AspectJ相关的annotation处理的相关方法,这个方法重写了父类的findCandidateadvisors(父类主要处理xml方式配置的advisor,这里添加了对注解声明的Adivisor的扫描,我们跳到BeanFactoryAspectJAdvisorsBuilder里面的buildAspectJAdvisors方法,从这个方法可以看到它从BeanFactory,也就是我们的Context里面取出所有的Bean,然后检查这个Bean是否有@Aspect注解,如果有的话则构建Advisor元数据,这里不直接构建Advisor实例,因为它由Spring IOC容器来管理。
AspectJ中的切入点匹配的执行点称作连接的(Join Point),在通知方法中可以声明一个JoinPoint类型的参数。通过JoinPoint可以访问连接点的细节。下面简要介绍JponPoint的方法:
1.java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
2.Signature getSignature() :获取连接点的方法签名对象;
3.java.lang.Object getTarget() :获取连接点所在的目标对象;
4.java.lang.Object getThis() :获取代理对象本身;
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
5.java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
6.java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的参数替换原来的参数。
package com.keke.userService.config.exception;
import com.keke.common.util.JwtTokenUtil;
import com.keke.common.util.ResultBase;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
*
*/
@Aspect
@Component
public class HttpAspect {
private final static Logger LOGGER = LoggerFactory.getLogger(HttpAspect.class);
@Autowired
private ExceptionHandle exceptionHandle;
// 对该注解的任何方法都切入
// execution1: 移除LoginController类 的所有方法(任意参数)
// execution2: controller 包下的所有子包所有类的所有方法(任意参数)
@Pointcut("!execution(* com.keke.userService.controller.LoginController.*(..)) && execution(* com.keke.userService.controller..*.*(..)) ")
public void log() {
}
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
//打印请求信息
printRequestInfo(joinPoint);
}
//打印请求信息
private void printRequestInfo(JoinPoint joinPoint){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// String token= request.getHeader("kexin_token");
//
// JwtTokenUtil.verifyToken(token);
// url
LOGGER.info("url={}", request.getRequestURL());
// method
LOGGER.info("method={}", request.getMethod());
// ip
LOGGER.info("id={}", request.getRemoteAddr());
// class_method
LOGGER.info("class_method={}",
joinPoint.getSignature().getDeclaringTypeName() + "," + joinPoint.getSignature().getName());
// args[]
LOGGER.info("args={}", joinPoint.getArgs());
}
@Around("log()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
ResultBase result = null;
try {
} catch (Exception e) {
return exceptionHandle.defaultErrorHandler(e);
}
if (result == null) {
return proceedingJoinPoint.proceed();
} else {
return result;
}
}
@AfterReturning(pointcut = "log()", returning = "object") // 打印输出结果
public void doAfterReturing(Object object) {
LOGGER.info("response={}", object.toString());
}
}
网友评论