(造轮子)手写Spring框架-PointcutAdvisor:Pointcut和Advice的组合

232 阅读1分钟

PointcutAdvisor:Pointcut和Advice的组合

代码地址:github.com/WangChao-ly…

建议订阅博主专栏,从下到上系统手写spring源码,体会其中过程!

Advisor是包含一个Pointcut和一个Advice的组合,Pointcut用于捕获JoinPoint,Advice决定在JoinPoint执行某种操作。实现了一个支持aspectj表达式的AspectJExpressionPointcutAdvisor。

新增以下接口和类

  • Advisor:该接口提供返回Advice的功能,能够返回自定义的拦截器,比如之前写的MethodBeforeAdvice等。
  • PointcutAdvisor:该接口继承了额Advisor接口,提供获取Pointcut方法。
  • AspectJExpressionPointcutAdvisor:该类扩展了AspectJExpressionPointcut类,将AspectJExpressionPointcut类作为属性聚合到类中,并提供了Advice和匹配表达式两个属性和相关接口。
public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor {
    private AspectJExpressionPointcut pointcut;
    private Advice advice;
    private String expression;

    public void setExpression(String expression){
        this.expression = expression;
        pointcut = new AspectJExpressionPointcut(expression);
    }

    @Override
    public Pointcut getPointcut() {
        return pointcut;
    }

    @Override
    public Advice getAdvice() {
        return advice;
    }

    // 设置方法拦截
    public void setAdvice(Advice advice){
        this.advice = advice;
    }
}

  • 测试方法:方法中将之前涉及到的代理AdvisedSupport和表达式匹配以及Before切面等结合起来,等知识点汇总起来。
@Test
public void testAdvisor() throws Exception{
    WorldService worldService = new WorldServiceImpl();

    //Advisor是Pointcut和Advice的组合
    String expression = "execution(* org.springframework.test.service.WorldService.explode(..))";
    AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();
    pointcutAdvisor.setExpression(expression);
    MethodBeforeAdviceInterceptor methodInterceptor = new MethodBeforeAdviceInterceptor(new WorldServiceBeforeAdvice());
    //注入方法拦截器
    pointcutAdvisor.setAdvice(methodInterceptor);

    //获取匹配到的类
    ClassFilter classFilter = pointcutAdvisor.getPointcut().getClassFilter();
    if(classFilter.matches(worldService.getClass())){
        AdvisedSupport advisedSupport = new AdvisedSupport();

        //对匹配到的类进行代理
        TargetSource targetSource = new TargetSource(worldService);
        advisedSupport.setTargetSource(targetSource);
        advisedSupport.setMethodInterceptor((MethodInterceptor) pointcutAdvisor.getAdvice());
        advisedSupport.setMethodMatcher(pointcutAdvisor.getPointcut().getMethodMatcher());
        advisedSupport.setProxyTargetClass(true);   //JDK or CGLIB

        WorldService proxy = (WorldService)new ProxyFactory(advisedSupport).getProxy();
        proxy.explode();
    }
}