首先,AOP是一种编程范式,是一种思想,是为了将通用逻辑从业务逻辑中分离出来,并且不写过多重复代码
这样做的好处是:1.可以集中处理某一关注点;2.可以方便的添加删除关注点;3.增强代码可读性,更加便于维护
他有如下几种应用场景:1.权限控制(用户登录,及用户权限可调用的接口等);2.缓存控制;3.事务控制;4.审计日志;5.性能监控;6.分布式追踪;7.异常处理
分享我在springboot项目中两种利用AOP模式添加日志的方法:
第一种利用@Aspect注解:
/**
* AOP实例(@Aspect作用是把当前类标识为一个切面供容器读取)
*
* @Author: liangxiao
* @Date: Created in 0:41 2018/5/25
*/
@Aspect
@Component
public class HttpAspect {
private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
@Pointcut("execution(public * com.liangxiao.demo.controller.GirlController.*(..))")
public void log() {
}
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//url
logger.info("url={}", request.getRequestURL());
//method
logger.info("method={}", request.getMethod());
//ip
logger.info("ip={}", request.getRemoteAddr());
//类方法
logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
//参数
logger.info("args={}", joinPoint.getArgs());
}
@After("log()")
public void doAfter() {
logger.info("2222222222222222222");
}
@AfterReturning(returning = "object",pointcut = "log()")
public void doAfterReturning(Object object){
logger.info("response={}",object.toString());
}
}
第二种实现HandlerInterceptor接口,并重写对应的方法:
/**
* 日志拦截器
*
* @author:liangxiao
* @date:2018/6/7
*/
@Component
public class LogInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class.getName());
@Autowired
protected RequestLogger requestLogger;
public static final String ANALYSIS_STRING = "@@ANALYSIS@@";
public static final String REQUEST_START_TIMESTAMP = "start_time";
private static final String ATTRIBUTE_HTTP_COST = "cost";
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
request.setAttribute(REQUEST_START_TIMESTAMP,
System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
Object name = request.getAttribute(ConstantUtil.REQUEST_CATEGORY);
if (name == null) {
return;
}
long cost = System.currentTimeMillis() - (Long) request.getAttribute(REQUEST_START_TIMESTAMP);
request.setAttribute(ATTRIBUTE_HTTP_COST, cost);
//vaquero log
LOGGER.info(ANALYSIS_STRING + " " + name + ".cost=" + cost + "ms");
//analyzer log
requestLogger.log((String) name, request, response);
}
}
这个需要在用WebMvcConfigurerAdapter配置一下,配置类如下:
/**
* 拦截器配置
* @author:liangxiao
* @date:2018/6/7
*/
@Configuration
@EnableWebMvc
public class InterceptorConfig extends WebMvcConfigurerAdapter {
@Autowired
private LogInterceptor logInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logInterceptor).addPathPatterns("/**");
}
}
如上我只是对Spring的AOP有初步的使用,进一步的优劣对比和原理,我将在后续的学习和使用中继续添加到我后续的博客中~