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用于把日志保存数据库
  /*  @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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值