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

来源:互联网 发布:淘宝店铺氛围图是什么 编辑:程序博客网 时间:2024/06/05 04:05

本文采用的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)@Documentedpublic @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;    }}


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 0
原创粉丝点击