文章目录

  • aop:aspectj-autoproxy
    • 属性
      • proxy-target-class
      • expose-proxy
    • 栗子
      • 切面
      • 被代理类
      • 配置
    • 解析
    • 原理
    • 总结
  • 拾遗
    • AOP切面的坑
      • 总结

aop:aspectj-autoproxy

此标签用以开启对于@AspectJ注解风格AOP的支持。

属性

proxy-target-class

你懂的。

expose-proxy

是否应该把代理对象暴露给AopContext,默认false。

栗子

切面

@Aspect
public class AspectDemo {@Pointcut("execution(void base.aop.AopDemo.send(..))")public void beforeSend() {}@Before("beforeSend()")public void before() {System.out.println("send之前");}
}

被代理类

public class AopDemo implements AopDemoInter {public void send() {System.out.println("send from aopdemo");}public void receive() {System.out.println("receive from aopdemo");}@Overridepublic void inter() {System.out.println("inter");}
}

配置

<aop:aspectj-autoproxy proxy-target-class="true" />
<bean class="base.aop.AopDemo" />
<bean class="base.aop.annotation.AspectDemo" />

因为AopDemo实现了AopDemoInter接口,但做实验的send方法又不在此接口里定义,所以只能用cglib的方式代理。

可以看出,即使标注了@Aspect注解,仍然需要将切面自己配置到Spring容器中。

解析

AspectJAutoProxyBeanDefinitionParser.parse:

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);extendBeanDefinition(element, parserContext);return null;
}

注册最终在AopConfigUtils.registerOrEscalateApcAsRequired方法中完成,创建器实际上是一个AnnotationAwareAspectJAutoProxyCreator类的对象,此类是前面AspectJAwareAdvisorAutoProxyCreator的子类。

原理

既然是AspectJAwareAdvisorAutoProxyCreator的子类,那么其代理子类的创建等核心逻辑自然是一样的。这里所需要关注的地方自然是所不一样的地方: 即是如何体现其注解的特性的。

前面说过,AspectJAwareAdvisorAutoProxyCreator通过findCandidateAdvisors方法来找到适用于bean的Advisor,所以注解的特性也是通过重写此方法来体现。

AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors:

@Override
protected List<Advisor> findCandidateAdvisors() {List<Advisor> advisors = super.findCandidateAdvisors();//这里advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());return advisors;
}

buildAspectJAdvisors方法所做的便是从容器中得到所有的bean,逐一判断是不是一个Aspect。那么判断Aspect的依据是什么?

AbstractAspectJAdvisorFactory.isAspect:

@Override
public boolean isAspect(Class<?> clazz) {return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

至于其它的实现细节不再探究。

总结

Spring对于AspectJ风格AOP的支持停留在外表(注解)上面,内部的实现仍然是自己的东西。

拾遗

AOP切面的坑

  1. 定义在private方法上的切面不会被执行,这个很容易理解,毕竟子类不能覆盖父类的私有方法。
  2. 同一个代理子类内部的方法相互调用不会再次执行切面。

这里以Cglib为例对第二点进行说明,cglib的相关核心组件可以参考前面CallbackFilter & Callback部分。对于配置了一个切面的典型场景,Spring内部的执行流程可总结如下图:

核心便是对目标方法的调用上,这里由CglibMethodInvocation的invokeJoinpoint实现:

@Override
protected Object invokeJoinpoint() throws Throwable {if (this.publicMethod) {return this.methodProxy.invoke(this.target, this.arguments);} else {return super.invokeJoinpoint();}
}

如果是非public方法,那么Spring将使用反射的方法对其进行调用,因为反射将其可访问性设为true。MethodProxy是Cglib对方法代理的抽象,这里的关键是方法调用的对象(目标)是我们的原生类对象,而不是Cglib代理子类的对象,这就从根本上决定了对同类方法的调用不会再次经过切面

总结

前面aop:aspectj-autoproxy-属性-expose-proxy一节提到了,Spring允许我们将代理子类暴露出来,可以进行如下配置:

<aop:config expose-proxy="true"><aop:advisor advice-ref="simpleMethodInterceptor" pointcut="execution(* aop.SimpleAopBean.*(..))" />
</aop:config>

当我们需要在一个被代理方法中调用同类的方法时(此方法也需要经过切面),可以这样调用:

public void testB() {System.out.println("testB执行");((SimpleAopBean) AopContext.currentProxy()).testC();
}

这里其实是一个ThreadLocal,当Cglib代理子类创建调用链之间便会将代理类设置到其中,DynamicAdvisedInterceptor.intercept相关源码:

if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;
}

aop:aspectj-autoproxy相关推荐

  1. Spring AOP + AspectJ Annotation Example---reference

    In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...

  2. Spring AOP / AspectJ AOP 的区别?

    Spring AOP / AspectJ AOP 的区别? Spring AOP属于运行时增强,而AspectJ是编译时增强. Spring AOP基于代理(Proxying),而AspectJ基于字 ...

  3. 解决:ClassNotFoundException: com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 场景,springcloud 学习工程中,把 feign 和 ribbon 工程 作为应用服务 ...

  4. Spring3系列12-Spring AOP AspectJ

    本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...

  5. Spring AOP AspectJ

    本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...

  6. Spring 之AOP AspectJ切入点语法详解(最全了,不需要再去其他地找了)---zhangkaitao

    Spring 之AOP AspectJ切入点语法详解(最全了,不需要再去其他地找了) http://jinnianshilongnian.iteye.com/blog/1415606    --zha ...

  7. 关于 Spring AOP (AspectJ) 你该知晓的一切

    [版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/54629058 出自[zejian ...

  8. Spring AOP AspectJ Pointcut Expressions With Examples--转

    原文地址:http://howtodoinjava.com/spring/spring-aop/writing-spring-aop-aspectj-pointcut-expressions-with ...

  9. Spring AOP,AspectJ,CGLIB 有点晕

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...

  10. Spring AOP AspectJ 代码实例

    本文参考来源 http://examples.javacodegeeks.com/enterprise-java/spring/aop/spring-aop-aspectj-example/ http ...

最新文章

  1. [团队公告]博客园的敏捷软件开发团队成立了
  2. 微信小程序底部导航Tabbar
  3. 角谷定理python输出变化过程,Python 100例——第十章----定理与猜想
  4. Android中List、Set、Map数据结构详解
  5. Pandas dtypes
  6. Lintcode 51.上一个排列[Medium]
  7. Effective Use of Word Order for Text Categorization with Convolutional Neural Networks
  8. python struct_struct
  9. 如何用代码表白——matlab绘制玫瑰、爱心和I LOVE YOU
  10. 利用图像来测量的技术——数字图像相关法(DIC)
  11. windows下cfree5中%d输出浮点数的问题
  12. android电池容量查看器,Android AccuBattery(电池损耗检测软件)V1.2.5 安卓专业版
  13. 找不到支撑位和压力位?看完本文可帮到你
  14. python读取excel的路径
  15. U3D RPC网络传输相机画面
  16. MemBrain2.0_论文
  17. Dell电脑 U盘启动盘 安装ubuntu
  18. Matlab | Lab4——用LU 分解法、 Jacobi 迭代、 Gauss-Seidel 迭代 解线性病态方程组(系数矩阵为Hilbert矩阵)
  19. 云计算介绍PPT2011-03版
  20. vue项目将多张图片生成一个gif动图

热门文章

  1. 计算机一级常用计算公式,软考网络工程师常用计算公式汇总1
  2. 怎么看mmdetection版本_mmdetection使用指南
  3. matlab画单位圆的代码,请问用MATLAB软件,以动画的形式作出单位圆x^2 +y^2 = 1的图像的程序代码是什么?...
  4. 网页设计常用色彩搭配表 - 配色表
  5. 【刷题篇】鹅厂文化衫问题
  6. [Other]规范的邮件签名格式及HTML代码
  7. 69 MyBatis和Spring整合
  8. JAVA:JDBC数据库编程
  9. KubeSphere介绍和基于K8S的安装
  10. Anaconda基本教程及常用命令(介绍、安装、基本操作、管理环境、管理包、conda和pip以及借助pqi换源)