Aop 切入点表达式

Spring中通过切入点表达式定义具体切入点,其常用AOP切入点表达式定义及说明:
表-1 Spring AOP 中切入点表达式说明
指示符 作用
bean 用于匹配指定bean对象的所有方法
within 用于匹配指定包下所有类内的所有方法
execution 用于按指定语法规则匹配到具体方法
@annotation 用于匹配指定注解修饰的方法

bean表达式一般应用于类级别,实现粗粒度的切入点定义,案例分析:
bean(“userServiceImpl”)指定一个userServiceImpl类中所有方法。
bean("*ServiceImpl")指定所有后缀为ServiceImpl的类中所有方法。
说明:bean表达式内部的对象是由spring容器管理的一个bean对象,表达式内部的名字应该是spring容器中某个bean的name。

within表达式应用于类级别,实现粗粒度的切入点表达式定义,案例分析:
within(“aop.service.UserServiceImpl”)指定当前包中这个类内部的所有方法。
within(“aop.service.") 指定当前目录下的所有类的所有方法。 within("aop.service…”)
指定当前目录以及子目录中类的所有方法。 within表达式应用场景分析:
1)对所有业务bean都要进行功能增强,但是bean名字又没有规则。 2)按业务模块(不同包下的业务)对bean对象进行业务功能增强。

execution表达式应用于方法级别,实现细粒度的切入点表达式定义,案例分析: 语法:execution(返回值类型
包名.类名.方法名(参数列表))。 execution(void
aop.service.UserServiceImpl.addUser())匹配addUser方法。 execution(void
aop.service.PersonServiceImpl.addUser(String))
方法参数必须为String的addUser方法。 execution(* aop.service….(…)) 万能配置。

@annotaion表达式应用于方法级别,实现细粒度的切入点表达式定义,案例分析 @annotation(anno.RequiredLog)
匹配有此注解描述的方法。 @annotation(anno.RequiredCache) 匹配有此注解描述的方法。
其中:RequiredLog为我们自己定义的注解,当我们使用@RequiredLog注解修饰业务层方法时,系统底层会在执行此方法时进行日扩展操作。

示例:

@Order(1)
@Slf4j
@Component
@Aspect
// aspect 注解描述的类型为spring AOP中的切面类型
public class SysLogAspect {

    @Autowired
    private SysLogService logService;

    // 切入点

    /**
     * bean 为 切入点类型
     * sysUserServiceImpl 为spring容器中的bean
     * <p>
     * 这里的含义是 当sysUserServiceImpl 中的每一个方法执行时 都由本
     * 切面对象的通知方法做功能增强
     */
    //@Pointcut("bean(sysUserServiceImpl)")

    // 使用自定义注解作为切入点
    @Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
    public void doLogPointcut() {
    }

    ;


    /**
     * 环绕通知 相对于其他的通知 优先级最高
     *
     * @param joinPoint 为一个连接对象 封装了正在要执行的目标方法
     * @return 目标方法的执行结果
     * @throws Throwable
     */
    @Around("doLogPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //log.info("method SysLog start {}",df.format(new Date()));
        try {
            long startTime = System.currentTimeMillis();
            Object result = joinPoint.proceed(); // 最终会执行的方法
            long endTime = System.currentTimeMillis();
            long time = endTime - startTime;
            // 将用户的操作日志写入数据库
            saveLog(joinPoint, time);
            //log.info("method SysLog end{}",df.format(new Date()));
            return result;
        } catch (Throwable e) {
            log.error("method SysLog error {},{}", df.format(new Date()), e.getMessage());
            throw e;
        }
    }

    // 将用户的操作日志写入数据库
    private void saveLog(ProceedingJoinPoint joinPoint, Long time) throws Exception {
        // 1.获取用户行为信息
        // 目标对象类型
        Class<?> jpCls = joinPoint.getTarget().getClass();
        // 获取方法签名对象(这个方法封装了要执行的目标方法信息)
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        String MethodName = jpCls.getName() + "." + ms.getName();

        // 获取目标方法对象 ,基于此对象获取方法上的RequiredLog注解,进而去到注解的值
        Method method = jpCls.getMethod(ms.getName(), ms.getParameterTypes());
        RequiredLog requiredLog = method.getAnnotation(RequiredLog.class);
        String annotationValue = requiredLog.value();
        // 2.构建用户对象 入库
        SysLog log = new SysLog();
        log.setIp(IPUtils.getIpAddr()); // 本机ip
        log.setMethod(MethodName); // 类名 + 方法名
        log.setOperation(annotationValue); // 操作
        log.setParams(Arrays.toString(joinPoint.getArgs())); // 参数
        log.setTime(time); // 执行时长
        log.setCreatedTime(new Date()); // 创建时间
        log.setUsername("admin"); // 操作用户
        logService.saveObject(log); // 入库

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值