Spring AOP

AOP简介

这里回答以下几个问题:

  1. 为什么需要AOP?
    AOP(Aspect-Oriented Programming)是面向切面编程的一种方式,面向对象的一种补充。实际的应用有:日志,事务,统一异常处理,锁,权限控制等等。
  2. AOP的底层实现?
    AOP底层实现有2种,JDK基于接口的实现通过实现类的方式对代码增强,CGlib对于类的实现通过生成子类的方式对代码增强。
  3. AOP包含哪些核心概念?
    ● 切面Aspect: 需要增强的某一个方法。
    ● 通知Advice: 实现增强的代码逻辑,有前置,后置,环绕,异常,正常行为后的通知等。
    ● 切点Pointcut: 用来需要增强的切面。

Spring AOP应用

方法出入口日志统一输出

import com.github.yn.framework.common.HandleResult;
import com.github.yn.framework.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;

/**
 * 日志切面逻辑处理
 *
 * @author chenjn
 * @version LogAspect.java, v 0.1 2022-11-25 9:40 PM chenjn
 */
@Slf4j
@Aspect
@Order(2)
public class LogAspect {

    public LogAspect() {
    }
    
	// -- 声明切点
    @Pointcut("@within(com.github.yn.framework.common.annotation.YnLog) && execution(public * *(..))")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        HandleResult<Object> handleResult = LogTemplate.get(joinPoint::proceed, joinPoint.getArgs());
        if (handleResult.isFail()) {
            throw BusinessException.of(handleResult.getMessage());
        }
        return handleResult.getData();
    }

}

// --- YnLog

/**
 * 日志标记
 *
 * @author chenjn
 * @Classname YnAlias
 * @Date 2020/10/16
 */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface YnLog {
}

// ----- LogTemplate

import com.alibaba.fastjson.JSON;
import com.github.yn.framework.common.HandleResult;
import com.github.yn.framework.common.SupplierThrow;
import com.github.yn.framework.common.exception.BaseException;
import com.github.yn.framework.common.exception.BusinessException;
import com.github.yn.framework.common.exception.E;
import com.github.yn.framework.common.exception.EMessage;
import lombok.extern.slf4j.Slf4j;

import java.util.function.Function;

/**
 *
 * 日志模板
 *
 * @author chenjn
 * @version LogTemplate.java, v 0.1 2022-11-26 8:38 AM chenjn
 */
@Slf4j
public class LogTemplate {

    public final static <T,R> HandleResult<R> get(SupplierThrow<R> supplier, T... param) {
        long startTime = System.currentTimeMillis();
        long endTime = startTime;

        boolean fail = false;
        R result = null;
        E err = null;
        try {
            log.info("LogTemplate[]exec start param:{}", JSON.toJSONString(param));
            result = supplier.get();
        } catch (BaseException e) {
            log.warn("LogTemplate[]exec base fail,e",e);
            err = e.getELatest();
            fail = true;
        } catch (Throwable e) {
            log.warn("LogTemplate[]exec unknow fail,e",e);
            err = EMessage.SYSTEM_WARNING;
            fail = true;
        } finally {
            endTime = System.currentTimeMillis();
        }

        HandleResult handleResult = fail ? HandleResult.fail(err)
                : HandleResult.ok(result);
        log.info("LogTemplate[]exec end handleResult:{},COST:{} ms",JSON.toJSONString(handleResult),endTime - startTime);

        return handleResult;
    }

}

Spring AOP方案设计

代理对象创建入口

代理对象是在创建Spring Bean的时候,有个初始化Bean的过程,在那里创建代理对象来顶替Spring bean。具体实现的类是AnnotationAwareAspectJAutoProxyCreator。
在这里插入图片描述

上图是AnnotationAwareAspectJAutoProxyCreator的一个关系,其中比较重要的另外两个就是AbstractAutoProxyCreator实现了postProcessAfterInitialization具体实现逻辑,BeanPostProcessor定义了postProcessAfterInitialization方法。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
    	Object cacheKey = getCacheKey(bean.getClass(), beanName);
    	if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 返回一个代理对象
        	return wrapIfNecessary(bean, beanName, cacheKey);
    	}
	}
	return bean;
}

代理对象创建

首先,声明AopProxyFactory,主要用来生成代理对象总的入口。
在这里插入图片描述

其次,通过声明AopProxy,来各自实现JDK动态代理,以及CGlib动态代理2种方式。
在这里插入图片描述

小结

首先,是对AOP的一个简介,他是对面向切面编程,是对面向对象的一个补充。他有切面,切点,通知等核心概念。接着是一个日志输入输出的应用实现,最后是SpringAOP逻辑的实现,比如代理对象创建入口,代理对象创建的方式等。

补充说明

  1. 如何看源码?
    ● 在postProcessAfterInitialization打一个断点,在本地启动的时候,看下调用栈等。
    ● 看下接口定义了要做的事情。然后看下有哪些不同实现。
  2. 通知执行顺序
    ● 如果多个通知命中同一个切面,那么这个切面执行的时候,会有多个通知执行先后顺序的问题。Spring 生成通知数组的时候,会排序。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值