AOP切面编程

1.什么是AOP切面编程

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理,如下图所示:
在这里插入图片描述
在这里插入图片描述
相关引用 JavaGuide

2.多个切面的执行顺序如何控制?

// 值越小优先级越高
@Order(3)
@Component
@Aspect
public class LoggingAspect implements Ordered {

@Component
@Aspect
public class LoggingAspect implements Ordered {

    // ....

    @Override
    public int getOrder() {
        // 返回值越小优先级越高
        return 1;
    }
}

3. 使用切面编程实现日志打印

自定义注解

/**
 * 调用方法时打印日志
 * 
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InvokeLog {
}

课程学习截图
在这里插入图片描述

配置类
在这里插入图片描述

import com.chehejia.osd.server.common.auth.ContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * InvokeLog 切面类
 *
 */
@Aspect
@Component
@Slf4j
public class InvokeLogAspect {
    /**
     * 获取切入点
     */
    @Pointcut("@annotation(com.chehejia.osd.server.common.annotation.log.InvokeLog)")
    public void logPointCut() {
    }

    /**
     *  方法执行前的动作
     *
     * @param point 连接点的信息
     */
    @Before("logPointCut()")
    private void logBefore(JoinPoint point) {
        try {
            String className = point.getTarget().getClass().getSimpleName();
            String methodName = point.getSignature().getName();
            log.info("=======>[{}::{}]accept request: {}, {}", className, methodName, ContextHolder.getOwnerId(), point.getArgs());
        }
        catch (Exception e) {
            log.error("前置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
        }
    }

    /**
     * 方法执行完毕,返回前的动作
     *
     * @param point 连接点信息
     * @param result 方法返回值
     */
    @AfterReturning(value = "logPointCut()", returning = "result")
    private void logAfter(JoinPoint point, Object result) {
        try {
            String className = point.getTarget().getClass().getSimpleName();
            String methodName = point.getSignature().getName();
            log.info("=======>[{}::{}]success result: {}, {}", className, methodName, ContextHolder.getOwnerId(), result);
        }
        catch (Exception e) {
            log.error("后置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
        }
    }
}

4.Demo

import com.chehejia.osd.server.common.auth.ContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class InvokeLogAspect {
    /**
     * 获取切入点
     */
    @Pointcut("@annotation(com.chehejia.osd.server.common.annotation.log.InvokeLog)")
    public void logPointCut() {
    }

    /**
     *  方法执行前的动作
     *
     * @param point 连接点的信息
     */
    @Before("logPointCut()")
    private void logBefore(JoinPoint point) {
        try {
            String className = point.getTarget().getClass().getSimpleName();
            String methodName = point.getSignature().getName();
            log.info("=======>[{}::{}]accept request: {}, {}", className, methodName, ContextHolder.getOwnerId(), point.getArgs());
        }
        catch (Exception e) {
            log.error("前置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
        }
    }

    /**
     * 方法执行完毕,返回前的动作
     *
     * @param point 连接点信息
     * @param result 方法返回值
     */
    @AfterReturning(value = "logPointCut()", returning = "result")
    private void logAfter(JoinPoint point, Object result) {
        try {
            String className = point.getTarget().getClass().getSimpleName();
            String methodName = point.getSignature().getName();
            log.info("=======>[{}::{}]success result: {}, {}", className, methodName, ContextHolder.getOwnerId(), result);
        }
        catch (Exception e) {
            log.error("后置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
        }
    }
}

import java.lang.annotation.*;

/**
 * 调用方法时打印日志
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InvokeLog {
}

5. 极海讲切面

极海讲切面
// TODO

附录

1.Guide
2.java使用切面编程实现日志打印

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

boy快快长大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值