aop:aspectj-autoproxy
文章目录
- 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切面的坑
- 定义在private方法上的切面不会被执行,这个很容易理解,毕竟子类不能覆盖父类的私有方法。
- 同一个代理子类内部的方法相互调用不会再次执行切面。
这里以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相关推荐
- Spring AOP + AspectJ Annotation Example---reference
In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simp ...
- Spring AOP / AspectJ AOP 的区别?
Spring AOP / AspectJ AOP 的区别? Spring AOP属于运行时增强,而AspectJ是编译时增强. Spring AOP基于代理(Proxying),而AspectJ基于字 ...
- 解决:ClassNotFoundException: com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 场景,springcloud 学习工程中,把 feign 和 ribbon 工程 作为应用服务 ...
- Spring3系列12-Spring AOP AspectJ
本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...
- Spring AOP AspectJ
本文讲述使用AspectJ框架实现Spring AOP. 再重复一下Spring AOP中的三个概念, Advice:向程序内部注入的代码. Pointcut:注入Advice的位置,切入点,一般为某 ...
- Spring 之AOP AspectJ切入点语法详解(最全了,不需要再去其他地找了)---zhangkaitao
Spring 之AOP AspectJ切入点语法详解(最全了,不需要再去其他地找了) http://jinnianshilongnian.iteye.com/blog/1415606 --zha ...
- 关于 Spring AOP (AspectJ) 你该知晓的一切
[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/54629058 出自[zejian ...
- Spring AOP AspectJ Pointcut Expressions With Examples--转
原文地址:http://howtodoinjava.com/spring/spring-aop/writing-spring-aop-aspectj-pointcut-expressions-with ...
- Spring AOP,AspectJ,CGLIB 有点晕
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...
- Spring AOP AspectJ 代码实例
本文参考来源 http://examples.javacodegeeks.com/enterprise-java/spring/aop/spring-aop-aspectj-example/ http ...
最新文章
- [团队公告]博客园的敏捷软件开发团队成立了
- 微信小程序底部导航Tabbar
- 角谷定理python输出变化过程,Python 100例——第十章----定理与猜想
- Android中List、Set、Map数据结构详解
- Pandas dtypes
- Lintcode 51.上一个排列[Medium]
- Effective Use of Word Order for Text Categorization with Convolutional Neural Networks
- python struct_struct
- 如何用代码表白——matlab绘制玫瑰、爱心和I LOVE YOU
- 利用图像来测量的技术——数字图像相关法(DIC)
- windows下cfree5中%d输出浮点数的问题
- android电池容量查看器,Android AccuBattery(电池损耗检测软件)V1.2.5 安卓专业版
- 找不到支撑位和压力位?看完本文可帮到你
- python读取excel的路径
- U3D RPC网络传输相机画面
- MemBrain2.0_论文
- Dell电脑 U盘启动盘 安装ubuntu
- Matlab | Lab4——用LU 分解法、 Jacobi 迭代、 Gauss-Seidel 迭代 解线性病态方程组(系数矩阵为Hilbert矩阵)
- 云计算介绍PPT2011-03版
- vue项目将多张图片生成一个gif动图
热门文章
- 计算机一级常用计算公式,软考网络工程师常用计算公式汇总1
- 怎么看mmdetection版本_mmdetection使用指南
- matlab画单位圆的代码,请问用MATLAB软件,以动画的形式作出单位圆x^2 +y^2 = 1的图像的程序代码是什么?...
- 网页设计常用色彩搭配表 - 配色表
- 【刷题篇】鹅厂文化衫问题
- [Other]规范的邮件签名格式及HTML代码
- 69 MyBatis和Spring整合
- JAVA:JDBC数据库编程
- KubeSphere介绍和基于K8S的安装
- Anaconda基本教程及常用命令(介绍、安装、基本操作、管理环境、管理包、conda和pip以及借助pqi换源)