本文采用的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
此外,可以在前置通知、异常通知等通知中进行日志的处理
参考:http://blog.csdn.net/czmchen/article/details/42392985
http://blog.csdn.net/liuchuanhong1/article/details/55099753