AOP -- 注解 @Aspect 、@Pointcut

目录

1.基本概念

1.1.切面类 @Aspect

1.2.切点 @Pointcut

1.3.Advice

1.4.JoinPoint

1.5.运算符用法

1.6.@annotation(annotationType)

1.7.代理对象 

1.8.调用切面注解

 2.代码展示


写在前面:在开发过程中,需要对每个方法执行时进行日志记录、返回值的解析,简单整理一下有关AOP的相关知识点。

1.基本概念

1.1.切面类 @Aspect

定义切面类,加上@Aspect、@Component注解;(下文有展示)

1.2.切点 @Pointcut

 (1)指定切面方法

execution表达式

第一个*表示匹配任意的方法返回值,

..(两个点)表示零个或多个,

第一个..表示module包及其子包,

第二个*表示所有类,

第三个*表示所有方法,

第二个..表示方法的任意参数个数

    //org.jeecg.modules.dlglong.controller;
    //com.sd3e.projectmanager.controller.acceptanceApplication;

    @Pointcut("execution(public * org.jeecg.modules..*.*Controller.*(..))||execution(public * com.*.projectmanager..*.*Controller.*(..))")
    public void excudeService() {
        
    }

 @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    	long time1=System.currentTimeMillis();	
        Object result = pjp.proceed();
        long time2=System.currentTimeMillis();
        log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
        long start=System.currentTimeMillis();
        this.parseDictText(result);
        long end=System.currentTimeMillis();
        log.debug("注入字典到JSON数据  耗时"+(end-start)+"ms");
        return result;
    }
    @Pointcut("execution(public * com.rest.module..*.*(..))")
    public void getMethods() {
    }

 (2)指定注解 

在这里,自定义了一个注解类,方法加注解即可使用

    @Pointcut("@annotation(org.jeecg.common.aspect.annotation.PermissionData)")
    public void pointCut() {

    }
package org.jeecg.common.aspect.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
  *  数据权限注解
 * @Author taoyan
 * @Date 2019年4月11日
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
public @interface PermissionData {
	/**
	 * 暂时没用
	 * @return
	 */
	String value() default "";
	
	
	/**
	 * 配置菜单的组件路径,用于数据权限
	 */
	String pageComponent() default "";
}

    @Pointcut("@annotation(com.rest.utils.SysPlatLog)")
    public void withAnnotationMethods() {

    }
public @interface SysPlatLog {
    // 操作名称
    String operateName() default "";
    // 操作描述
    String logNote() default "";
}

1.3.Advice

在切入点上执行的增强处理,主要有五个注解: 

@Before  在切点方法之前执行

@After  在切点方法之后执行

@AfterReturning 切点方法返回后执行

@AfterThrowing 切点方法抛异常执行

@Around 属于环绕增强,能控制切点执行前,执行后

1.4.JoinPoint

方法中的参数JoinPoint为连接点对象,它可以获取当前切入的方法的参数、代理类等信息,因此可以记录一些信息,验证一些信息等;

1.5.运算符用法

使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系; 

   1.2.代码中给出了示例

1.6.@annotation(annotationType)

匹配指定注解为切入点的方法;

1.7.代理对象 

//aop代理对象
Object aThis = joinPoint.getThis();
//被代理对象
Object target = joinPoint.getTarget();

1.8.调用切面注解

	@AutoLog(value = "ws_xbx-分页列表查询")
	@ApiOperation(value="ws_xbx-分页列表查询", notes="ws_xbx-分页列表查询")
	@GetMapping(value = "/list")
	@PermissionData(pageComponent="sd3e/actDemo/WsXbxList")//sys_permission 表组件路径 component 字段
	public Result queryPageList(WsXbx wsXbx,
								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
								   HttpServletRequest req) {
		QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(wsXbx, req.getParameterMap());
		Page page = new Page(pageNo, pageSize);
		IPage pageList = wsXbxService.page(page, queryWrapper);
		return Result.OK(pageList);
	}

@SysPlatLog(operateName = "查看详情",logNote = "查看详情")
@SneakyThrows
public Result getItem(@RequestParam(required = false) String bs){
}

 2.代码展示

package com.npc.rest.utils;

import com.npc.rest.common.properites.AppSupPlatProperties;
import com.sys.model.SysLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.*;

@Aspect
@Slf4j
@Component
public class SysPlatLogAspect {

    /**
     * 指定切面
     */
    @Pointcut("execution(public * com.rest.module..*.*(..))")
    public void getMethods() {
   }
    /**
     * 指定注解
     */
    @Pointcut("@annotation(com.rest.utils.SysPlatLog)")
    public void withAnnotationMethods() {
    }

    /***
     * 拦截控制层的操作日志
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @After(value = "getMethods() && withAnnotationMethods()")
    public void recordLog(JoinPoint joinPoint) throws Throwable {
        SysLog sysLog = new SysLog();
        SysPlatLog sysPlatLog = getInter(joinPoint);
        sysLog.setOperateName(sysPlatLog.operateName());
        sysLog.setLogNote(sysPlatLog.logNote());
        sysLog.setLogTime(new Date());
        sysLog.setAppCode(AppSupPlatProperties.getAppCode());
    }

    public SysPlatLog getInter(JoinPoint joinPoint) throws ClassNotFoundException {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    SysPlatLog sysPlatLog = method.getAnnotation(SysPlatLog.class);
                    return sysPlatLog;
                }
            }
        }
        return null;
    }
}

多个切面执行顺序

你可能感兴趣的:(Java,Springboot,spring,aop,切面,Aspect,Pointcut)