springAOP进行自定义注解,用于方法的处理

2024-06-01 01:48

本文主要是介绍springAOP进行自定义注解,用于方法的处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文采用的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用于把日志保存数据库/*  @Resourceprivate 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对象ClassClass 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);//请求的IPString 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);//获取请求ipString 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对象ClassClass 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);//请求的IPString 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);//获取请求ipString 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

 

这篇关于springAOP进行自定义注解,用于方法的处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1019648

相关文章

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景

在Golang中实现定时任务的几种高效方法

《在Golang中实现定时任务的几种高效方法》本文将详细介绍在Golang中实现定时任务的几种高效方法,包括time包中的Ticker和Timer、第三方库cron的使用,以及基于channel和go... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系

在Linux终端中统计非二进制文件行数的实现方法

《在Linux终端中统计非二进制文件行数的实现方法》在Linux系统中,有时需要统计非二进制文件(如CSV、TXT文件)的行数,而不希望手动打开文件进行查看,例如,在处理大型日志文件、数据文件时,了解... 目录在linux终端中统计非二进制文件的行数技术背景实现步骤1. 使用wc命令2. 使用grep命令

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

XML重复查询一条Sql语句的解决方法

《XML重复查询一条Sql语句的解决方法》文章分析了XML重复查询与日志失效问题,指出因DTO缺少@Data注解导致日志无法格式化、空指针风险及参数穿透,进而引发性能灾难,解决方案为在Controll... 目录一、核心问题:从SQL重复执行到日志失效二、根因剖析:DTO断裂引发的级联故障三、解决方案:修复