本文采用的spring boot进行配置
maven 引入
<!-- spring boot aop starter依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
application.properties文件开启aop注解
spring.aop.auto = true;
自定义注解类
package com.kuaixin.crm.crm_tsale_kx_service.service.anno;
import java.lang.annotation.*;
/**
*自定义注解 拦截service
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemServiceType {
/**
* 方法描述
* @return
*/
String description() default "";
/**
* 方法类型 0 表示不进行处理,1 表示进行处理
* @return
*/
int type() default 0;
/**
* 类的元数据,用于指定需要转换为的目标格式
* @return
*/
Class classType();
}
切点类
package com.kuaixin.crm.crm_tsale_kx_service.service.anno;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2017/8/31.
* @desc 定义切点类,无论是前置通知还是后置通知、环绕通知以及异常通知,都需要在指定的方法上加上SystemServiceType注释就会生效
* 还可以在通知中记录日志
*/
@Component // 注册到Spring容器,必须加入这个注解
@Aspect // 该注解标示该类为切面类,切面是由通知和切点组成的。
public class SystemServiceTypeAspect {
//注入Service用于把日志保存数据库
/* @Resource
private LogService logService;*/
//日志记录对象
private final static Logger log = LogManager.getLogger(SystemServiceTypeAspect.class);
//Service层切点
@Pointcut("@annotation(com.kuaixin.crm.crm_tsale_kx_service.service.anno.SystemServiceType)")
public void serviceAspect() {
}
//controller层切点 com.kuaixin.crm.crm_tsale_kx_service.service.anno.SystemServiceType可以指定另外定义的注释接口
@Pointcut("@annotation(com.kuaixin.crm.crm_tsale_kx_service.service.anno.SystemServiceType)")
public void controllerAspect() {
}
/**
*对某个方法返回的结果进行处理后,如将entity转换为与前端交互的vo
*/
@Around(value = "serviceAspect()")
public Object aroundProcess(ProceedingJoinPoint pjp) throws Throwable {
Object retVal = pjp.proceed();
//*==========记录本地异常日志==========*//*
//logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);
//需要转换为的vo对象Class
Class vClass = getClassByAnno(pjp);
//数组或集合对象
if(retVal.getClass().isArray()||retVal instanceof List){
List list = new ArrayList<>();
for(Object origin:(List)retVal){
Object dest = vClass.newInstance();
BeanUtils.copyProperties(dest,origin);
list.add(dest);
}
return list;
}
//单个对象
Object dest = vClass.newInstance();
BeanUtils.copyProperties(dest,retVal);
return dest;
}
/**
* 前置通知
*
* @param joinPoint 切点
*/
@Before("serviceAspect()")
public void doBefore(JoinPoint joinPoint) {
//获得http请求
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//读取session中的用户
//User user = (User) session.getAttribute(WebConstants.CURRENT_USER);
//请求的IP
String ip = request.getRemoteAddr();
try {
String desc = getServiceMthodDescription(joinPoint);
log.info("getServiceMthodDescription:"+desc);
} catch (Exception e) {
log.error("aop处理异常:", e);
}
}
/**
* 后置通知
*
* @param joinPoint 切点
*/
@After("serviceAspect()")
public void doAfter(JoinPoint joinPoint) {
try {
String desc = getServiceMthodDescription(joinPoint);
log.info("getServiceMthodDescription:"+desc);
} catch (Exception e) {
log.error("aop处理异常:", e);
}
}
/**
* 异常通知 用于拦截service层记录异常日志
*
* @param joinPoint
* @param e
*/
@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//读取session中的用户
// User user = (User) session.getAttribute(WebConstants.CURRENT_USER);
//获取请求ip
String ip = request.getRemoteAddr();
//获取用户请求方法的参数并序列化为JSON格式字符串
String params = "";
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
}
//日志记录操作..............
/* Log log = SpringContextHolder.getBean("logxx");
log.setDescription(getControllerMethodDescription(joinPoint));
log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
log.setType("0");
log.setRequestIp(ip);
log.setExceptionCode( null);
log.setExceptionDetail( null);
log.setParams( null);
log.setCreateBy(user);
log.setCreateDate(DateUtil.getCurrentDate());
//保存数据库
logService.add(log);*/
}
/**
* 获取注解中对方法的描述信息type等 用于service层注解k
*
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
*/
public static String getServiceMthodDescription(JoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
SystemServiceType serviceType = method.getAnnotation(SystemServiceType.class);
//得到对应的方法结果
Class clazz = serviceType.classType();
int type = serviceType.type();
description = serviceType.description();
log.info("type:" + type);
break;
}
}
}
return description;
}
/***
* 获取aop拦截到的方法注解的Class
* @param pjp
* @return
*/
public static Class getClassByAnno(ProceedingJoinPoint pjp){
Class<?> aClass = pjp.getTarget().getClass();
Method[] methods = aClass.getMethods();
for (Method method : methods) {
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
// 获取注解的具体类型
Class<? extends Annotation> annotationType = annotation.annotationType();
//比较当前方法注解是否是SystemServiceType注解
if (SystemServiceType.class == annotationType) {
log.info("方法:" + method.getName() + "()\t" + SystemServiceType.class.getName());
SystemServiceType serviceType = method.getAnnotation(SystemServiceType.class);
//得到对应的方法结果
Class clazz = serviceType.classType();
int type = serviceType.type();
String desc = serviceType.description();
return clazz;
}
}
}
return null;
}
}
Object retVal = pjp.proceed();
//*==========记录本地异常日志==========*//*
//logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);
//需要转换为的vo对象Class
Class vClass = getClassByAnno(pjp);
//数组或集合对象
if(retVal.getClass().isArray()||retVal instanceof List){
List list = new ArrayList<>();
for(Object origin:(List)retVal){
Object dest = vClass.newInstance();
BeanUtils.copyProperties(dest,origin);
list.add(dest);
}
return list;
}
//单个对象
Object dest = vClass.newInstance();
BeanUtils.copyProperties(dest,retVal);
return dest;
}
/**
* 前置通知
*
* @param joinPoint 切点
*/
@Before("serviceAspect()")
public void doBefore(JoinPoint joinPoint) {
//获得http请求
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//读取session中的用户
//User user = (User) session.getAttribute(WebConstants.CURRENT_USER);
//请求的IP
String ip = request.getRemoteAddr();
try {
String desc = getServiceMthodDescription(joinPoint);
log.info("getServiceMthodDescription:"+desc);
} catch (Exception e) {
log.error("aop处理异常:", e);
}
}
/**
* 后置通知
*
* @param joinPoint 切点
*/
@After("serviceAspect()")
public void doAfter(JoinPoint joinPoint) {
try {
String desc = getServiceMthodDescription(joinPoint);
log.info("getServiceMthodDescription:"+desc);
} catch (Exception e) {
log.error("aop处理异常:", e);
}
}
/**
* 异常通知 用于拦截service层记录异常日志
*
* @param joinPoint
* @param e
*/
@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//读取session中的用户
// User user = (User) session.getAttribute(WebConstants.CURRENT_USER);
//获取请求ip
String ip = request.getRemoteAddr();
//获取用户请求方法的参数并序列化为JSON格式字符串
String params = "";
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
}
//日志记录操作..............
/* Log log = SpringContextHolder.getBean("logxx");
log.setDescription(getControllerMethodDescription(joinPoint));
log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
log.setType("0");
log.setRequestIp(ip);
log.setExceptionCode( null);
log.setExceptionDetail( null);
log.setParams( null);
log.setCreateBy(user);
log.setCreateDate(DateUtil.getCurrentDate());
//保存数据库
logService.add(log);*/
}
/**
* 获取注解中对方法的描述信息type等 用于service层注解k
*
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
*/
public static String getServiceMthodDescription(JoinPoint joinPoint)
throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
SystemServiceType serviceType = method.getAnnotation(SystemServiceType.class);
//得到对应的方法结果
Class clazz = serviceType.classType();
int type = serviceType.type();
description = serviceType.description();
log.info("type:" + type);
break;
}
}
}
return description;
}
/***
* 获取aop拦截到的方法注解的Class
* @param pjp
* @return
*/
public static Class getClassByAnno(ProceedingJoinPoint pjp){
Class<?> aClass = pjp.getTarget().getClass();
Method[] methods = aClass.getMethods();
for (Method method : methods) {
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
// 获取注解的具体类型
Class<? extends Annotation> annotationType = annotation.annotationType();
//比较当前方法注解是否是SystemServiceType注解
if (SystemServiceType.class == annotationType) {
log.info("方法:" + method.getName() + "()\t" + SystemServiceType.class.getName());
SystemServiceType serviceType = method.getAnnotation(SystemServiceType.class);
//得到对应的方法结果
Class clazz = serviceType.classType();
int type = serviceType.type();
String desc = serviceType.description();
return clazz;
}
}
}
return null;
}
}
service或controller层调用
@SystemServiceType(type = 1,description = "根据pcode获取下级列表",classType = SysDictionaryInfoVO.class)
public Object getChildDicVosByPcode(String pcode) throws Exception{
List<SysDictionaryInfo> dictionaryInfos = dictionaryInfoMapper.selectChildDictionaryByPcode(pcode);
List<SysDictionaryInfoVO> sysDictionaryInfoVOs = new ArrayList<SysDictionaryInfoVO>();
return dictionaryInfos;
}
这里将会对返回结果dictionaryInfos为SysDictionaryInfo集合,在Around环绕通知进行结果的转换,返回的结果为SysDictionaryInfoVO,
由于转换前和转换后的类型不一样,所有需要定义方法的返回类型为Object
此外,可以在前置通知、异常通知等通知中进行日志的处理
参考: