SpringAop源码(一)- 深入理解Aop基本概念

目录

一、Spring Aop编码实现

二、Spring Aop概念分析

1、目标对象(TargetSource)

2、增强(Advice)

3、连接点(Joinpoint)

4、切入点(Pointcut)

5、切面(Advisor)

6、织入


    一直在考虑从哪里开始梳理,看到Spring的Aop包就大概明白了。首先,虽然Aop不是Spring的第二大特性,但是并不是Spring的产物。看一下包就知道了:

    包被分为两个部分,一个是aopalliance(Aop联盟)制定的概念或者接口定义;一个是springframework.aop,Spring对联盟提出的概念的一个实现。那么还是需要从几个Aop的概念开始,因为Spring就是对其进行实现。Spring Aop编码实现:

一、Spring Aop编码实现

    还是使用动态代理的接口和实现:

public interface DemoService {

    String doSomething(String arg);

    String doOther(String arg);
}
public class DemoServiceImpl implements DemoService {
    @Override
    public String doSomething(String arg) {
        System.out.println("doSomething!!!");
        return "ok";
    }

    @Override
    public String doOther(String arg) {
        System.out.println("doOther!!!");
        return "other";
    }
}
public class AopAdvice /*extends AopInvocationException*/ implements MethodBeforeAdvice,
        MethodInterceptor,
        org.aopalliance.intercept.MethodInterceptor,
        AfterReturningAdvice{

    /**
     *  前置Aop
     * @param method 代理方法
     * @param args 方法参数
     * @param target 代理对象
     * @throws Throwable
     * @see MethodBeforeAdvice
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("before 执行了!");
    }

    /**
     *  cglib代理特殊处理
     * @param o 代理对象
     * @param method 方法本身
     * @param objects 方法参数
     * @param methodProxy 代理对象
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, 
        MethodProxy methodProxy) throws Throwable {
        System.out.println("实现cglib调用!");

        Object invoke = methodProxy.invoke(o, objects);
        return invoke;
    }

    /**
     *  Around Aop
     * @param invocation 方法代理
     * @return 执行返回
     * @throws Throwable 异常
     * @see org.aopalliance.intercept.MethodInterceptor
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Around 前执行了!");

        Object proceed = invocation.proceed();

        System.out.println("Around 后执行了!");
        return proceed;
    }

    /**
     *  后置 Aop
     * @param returnValue 返回值
     * @param method 方法
     * @param args 参数
     * @param target 代理对象
     * @throws Throwable 异常
     */
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, 
        Object target) throws Throwable {
        System.out.println("afterReturning 执行了");
    }
}

执行测试:

public class AopTest {

    public static void main(String[] args) {
        // 自动代理
        ProxyFactory proxyFactory = new ProxyFactory();
        // 目标对象(DemoServiceImpl)
        proxyFactory.setTarget(new DemoServiceImpl());
        // 增强(AopAdvice)
        AopAdvice aopAdvice = new AopAdvice();
//        proxyFactory.addAdvice();
        // 切点(DemoStaticPointcutAdvisor)
        DemoStaticPointcutAdvisor advisor = new DemoStaticPointcutAdvisor();
        advisor.setAdvice(aopAdvice);
        proxyFactory.addAdvisor(advisor);

        // 从代理工厂 获取 切面
        DemoService demoService = (DemoService)proxyFactory.getProxy();
        System.out.println("----------------------------");
        demoService.doSomething("kevin!");
        System.out.println("----------------------------");
        demoService.doOther("kevin!");
        System.out.println("----------------------------");
    }
}

执行结果:

二、Spring Aop概念分析

1、目标对象(TargetSource

    Spring Aop使用动态代理机制实现,那么目标对象就比较好理解(动态代理可以参见代理模式-静态代理、JDK和Cglib动态代理)。目标对象就是上面demo中的new DemoServiceImpl(),在Spring中目标对象用TargerSource进行表示,并且引入了很多子类,如下:

比如我们刚才demo中setTarget方法,如下:

public void setTarget(Object target) {
    setTargetSource(new SingletonTargetSource(target));
}

@Override
public void setTargetSource(@Nullable TargetSource targetSource) {
    this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}

TargetSource结构如下,比较好理解:

public interface TargetSource extends TargetClassAware {

    @Override
    @Nullable
    Class<?> getTargetClass();

    boolean isStatic();

    @Nullable
    Object getTarget() throws Exception;

    rows Exception if the object can't be released

    void releaseTarget(Object target) throws Exception;
}

2、增强(Advice

    实现Aop我们可以在被代理的方法前执行,也可以在方法后执行,所以增强还是比较形象的。在Spring中使用Advice接口进行表示。如下:

如上大致可以分为,前置增强(BeforeAdvice)、后置增强(AfterAdvice)、环绕增强(Inteceptor下面的,主要包括MethodInteceptor的invoke回调方法实现的环绕增强,构造增强)、引介增强(DynamicInstroductionAdvice下面的,引介增强就是给目标对象织入没有的方法,拿到代理对象后就可以直接调用其他织入的方法)、AspectJ增强(AbstractAspectJAdvice)。

从上面的执行结果我们看到了执行顺序:

环绕增强(Around)的前增强: MethodInteceptor的invoke回调方法中,invocation.proceed();执行的代码

前置增强(Before):MethodBeforeAdvice的before回调方法

后置增强(After):AfterReturningAdvice的after回调方法

环绕增强(Around)的后增强:MethodInteceptor的invoke回调方法中,invocation.proceed();执行的代码

3、连接点(Joinpoint)

    我们使用动态代理实现切面功能的时候,默认会对目标对象的所有的方法都进行增强,但是这很多时候并不是我们想要的,比如上面的时候。那么Spring中使用Pointcut表示需要进行增强的目标对象方法,并且Spring只支持方法级别的切面(不支持比如对访问一个字段的切面)。

 

4、切入点(Pointcut)

    理解了连接点,切入点就是一组连接点的集合。

    大致分为 DynamicMethodMatchPointcut(动态方法匹配切点)、ExpressionPointcut(Spring Expression的匹配切点)、AnnotationMatchingPointcut(注解匹配切点)、StaticMethodMatchPointcut(静态方法匹配切点)。静态方法连接点只需要变异完之后就可以确认,比如根据方法名称进行判断;动态匹配可能会对参数值进行动态判断等。每种匹配都用的还是比较多的,后面源码分析中非常多。

5、切面(Advisor)

 切面就是在哪个切点上进行什么增强。所以我理解:切面 = 切点 + 增强 。在Spring中使用接口Advisor表示切面。主要又分为普通切面(PointcutAdvisor)和引介切面(IntroductionAdvisor)。而普通切面非常多,也经常见,如下:

  • 1、StaticMethodMatcherPointcutAdvisor,静态方法匹配切点的切面还是很形象的,我们刚才使用的就是该切面
  • 2、AbstractBeanFactoryPointcutAdvisor,Spring Bean工厂相关的切面,很多地方都在使用
  • 3、RegexpMethodPointcutAdvisor,正则匹配方法切面
  • 4、AspectJExpressionPointcutAdvisor,AspectJ使用Spring的Expression匹配的切面
  • 5、NameMatchMethodPointcutAdvisor,匹配方法名称的拦截器
  • 6、DefaultPointcutAdvisor,最常用的切面类型,它可以通过任意Pointcut和Advice定义一个切面,唯一不支持的就是引介的切面类型,一般可以通过扩展该类实现自定义的切面。
  • 7、AsyncAnnotationAdvisor,我们使用@Async("aaa"),使方法在线程池异步执行,详细可以参见:Spring源码-@Async原理分析
  • 8、TransactionAttributeSourceAdvisor,Spring的声明式事务使用的切面,详细可以参见:Spring源码-@EnableTransactionManagement方式事务实现分析(上)

 

6、织入

上面已经定义了在目标对象的哪些连接点(切点)干什么事(增强),那么这一系列组成的功能块,我理解为切面。比如,我使用Aop实现了一个方法性能监控组件。

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值