Spring框架之AOP PointCut切入点底层实现原理

手写Spring框架之 AOP PointCut切入点底层实现原理

Spring的PointCut切入点以及相关切点表达式的解析逻辑实际上不是在Spring当中自己实现的,而是调用了AspectJ的相关接口,这也是为什么在Spring AOP当中会大量出现AspectJ相关注解如,@Aspect,@Before等等

源码见:mini-spring
在这里插入图片描述

一,AspectJ与Spring AOP之间的关系

Spring AOP是利用的动态代理机制,如果一个Bean实现了接口,那么就会采用JDK动态代理来生成该接口的代理对象,如果一个Bean没有实现接口,那么就会采用CGLIB来生成当前类的一个代理对象。代理对象的作用就是代理原本的Bean对象,代理对象在执行某个方法时,会在该方法的基础上增加一些切面逻辑,使得我们可以利用AOP来实现一些诸如登录校验、权限控制、日志记录等统一功能。

Spring AOP和Aspect之间并没有特别强的关系,AOP表示面向切面编程,这是一种思想,各个组织和个人都可以通过技术来实现这种思想,AspectJ就是其中之一,它会在编译期来对类进行增强,所以要用Aspect,得用Aspect开发的编译器来编泽你的项目。而Spring AOP则是米用动态代理的方式来实现AOP,只不过觉得Aspect中设计的那几个注解比较好,比如@Before、@After、@Around等,同时也不给程序员造成困扰,所以Spring
AOP中会对这几个注解进行支持,虽然注解是相同的,但是底层的支持实现是完全不一样的。

二,底层实现

#PointCut

定义切点接口,用于选择性地应用通知(Advice)到目标类的特定方法上
切点通过类过滤器(ClassFilter)和方法匹配器(MethodMatcher)来确定应用通知的方法

/**  
 * 定义切点接口,用于选择性地应用通知(Advice)到目标类的特定方法上  
 * 切点通过类过滤器(ClassFilter)和方法匹配器(MethodMatcher)来确定应用通知的方法  
 *  
 * @author jixu  
 * @title PointCut  
 * @date 2025/5/20 15:47  
 */
public interface PointCut {  
  
    /**  
     * 获取类过滤器,用于判断哪些类需要应用通知  
     *  
     * @return ClassFilter 实例,用于过滤目标类  
     */  
    ClassFilter getClassFilter();  
  
    /**  
     * 获取方法匹配器,用于判断目标类中的哪些方法需要应用通知  
     *  
     * @return MethodMatcher 实例,用于匹配目标方法  
     */  
    MethodMatcher getMethodMatcher();  
}

#MethodMatcher

MethodMatcher接口用于定义方法匹配规则。它主要用于判断一个给定的方法是否与当前上下文中的方法匹配。
这个接口在需要对方法进行筛选或条件判断时非常有用, 例如在AOP(面向切面编程)中,确定哪些方法需要应用切面逻辑。

/**  
 * MethodMatcher接口用于定义方法匹配规则。  
 * 它主要用于判断一个给定的方法是否与当前上下文中的方法匹配。  
 * 这个接口在需要对方法进行筛选或条件判断时非常有用,  
 * 例如在AOP(面向切面编程)中,确定哪些方法需要应用切面逻辑。  
 *  
 * @author jixu  
 * @title MethodMatcher  
 * @date 2025/5/20 15:46  
 */
public interface MethodMatcher {  
  
    /**  
     * 判断给定的方法是否与当前上下文中的方法匹配。  
     *  
     * @param method 要检查的方法  
     * @param targetClass 目标类,即方法所属的类  
     * @return 如果方法匹配则返回true,否则返回false  
     */    
     boolean matches(Method method , Class<?> targetClass);  
}

#ClassFilter

ClassFilter接口用于定义类过滤器,它帮助筛选出满足特定条件的类

/**  
 * ClassFilter接口用于定义类过滤器,它帮助筛选出满足特定条件的类  
 * 这个接口主要用于框架内部,以决定哪些类需要被处理或关注  
 *  
 * @author jixu  
 * @date 2025/5/20 15:45  
 */
public interface ClassFilter {  
  
    /**  
     * 判断目标类是否匹配过滤条件  
     * 此方法由实现ClassFilter接口的类来具体实现,用于定义匹配逻辑  
     *  
     * @param clazz 待筛选的目标类  
     * @return 如果目标类匹配过滤条件,则返回true;否则返回false  
     */    
     boolean matches(Class<?> clazz);  
}

#AspectJExpressionPointcut

该类主要用于定义AspectJ的切点表达式,以便在面向切面编程(AOP)中 精确定义哪些方法或代码块需要应用切面逻辑,如日志记录、性能监控等

  
/**  
 * AspectJ表达式切点类  
 * 该类主要用于定义AspectJ的切点表达式,以便在面向切面编程(AOP)中  
 * 精确定义哪些方法或代码块需要应用切面逻辑,如日志记录、性能监控等  
 *   
* @author jixu  
 * @title AspectJExpressionPointcut  
 * @date 2025/5/20 16:33  
 */
public class AspectJExpressionPointcut implements ClassFilter , MethodMatcher , PointCut {  
  
    // 定义支持的切入函数  
    private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();  
  
    static {  
        // 加入支持的切入方法  
        SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);  
    }  
  
    private final PointcutExpression pointcutExpression;  
  
  
    // 通过构造函数传入具体的切点表达式,解析为PointcutExpression  
    public AspectJExpressionPointcut(String expression) {  
        PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, this.getClass().getClassLoader());  
        pointcutExpression = pointcutParser.parsePointcutExpression(expression);  
    }  
  
  
  
  
    /**  
     * 判断目标类是否匹配过滤条件  
     * 此方法由实现ClassFilter接口的类来具体实现,用于定义匹配逻辑  
     *  
     * @param clazz 待筛选的目标类  
     * @return 如果目标类匹配过滤条件,则返回true;否则返回false  
     */    @Override  
    public boolean matches(Class<?> clazz) {  
        return pointcutExpression.couldMatchJoinPointsInType(clazz);  
    }  
  
    /**  
     * 判断给定的方法是否与当前上下文中的方法匹配。  
     *  
     * @param method      要检查的方法  
     * @param targetClass 目标类,即方法所属的类  
     * @return 如果方法匹配则返回true,否则返回false  
     */    @Override  
    public boolean matches(Method method, Class<?> targetClass) {  
        return pointcutExpression.matchesMethodExecution(method).alwaysMatches();  
    }  
  
    /**  
     * 获取类过滤器,用于判断哪些类需要应用通知  
     *  
     * @return ClassFilter 实例,用于过滤目标类  
     */  
    @Override  
    public ClassFilter getClassFilter() {  
        return this;  
    }  
  
    /**  
     * 获取方法匹配器,用于判断目标类中的哪些方法需要应用通知  
     *  
     * @return MethodMatcher 实例,用于匹配目标方法  
     */  
    @Override  
    public MethodMatcher getMethodMatcher() {  
        return this;  
    }  
}

三,测试

public class PointCutTest {  
  
    @Test  
    public void testPointCut() throws NoSuchMethodException {  
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut("execution(* org.qlspringframework.beans.ioc.service.HelloService.*(..))");  
  
        Class<HelloService> helloServiceClass = HelloService.class;  
        Method declaredMethod = helloServiceClass.getDeclaredMethod("say");  
  
        Assert.assertEquals(pointcut.matches(helloServiceClass),true);  
        Assert.assertEquals(pointcut.matches(declaredMethod,helloServiceClass),true);  
  
    }  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

攒了一袋星辰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值