Spring AOP 的proxy详解
spring 提供了多种不同的方案实现对 bean 的 aop proxy, 包括 ProxyFactoryBean, 便利的 TransactionProxyFactoryBean 以及 AutoProxyCreator 等,
下图是 proxy class diagram 以供参考
这里重点说一下最常用的 ProxyFactoryBean, TransactionProxyFactoryBean, BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator 的联系和区别
1.
ProxyFactoryBean : 使用率最高的 proxy 方式, 它通过配置 interceptorNames 属性决定加入哪些
advisor (method interceptor 将会被自动包装成 advisor, 下文将描述这个细节),
注意是 "interceptorNames" 而不是 "interceptors",
原因是 ProxyFactoryBean 可能返回非 singleton 的 proxy 实例, 而 advisior 可能也是非 singleton 的,
因此不能通过 interceptor reference 来注入
2. TransactionProxyFactoryBean : 特定用于 transaction proxy, 注意其 super class 是 AbstractSingletonProxyFactoryBean, 也就是说,
TransactionProxyFactoryBean 永远无法返回非 singleton 的 proxy 实例 !!!
如果你需要非 singleton 的 proxy 实例, 请考虑使用 ProxyFactoryBean.
3.
BeanNameAutoProxyCreator : 故名思义, 根据 bean name 进行 auto proxy, bean name 的
match 规则参见 org.springframework.util.PatternMatchUtils
4. DefaultAdvisorAutoProxyCreator : 更强大的 auto proxy creator, 强大之处在于它会 cahce 容器中所有注册的 advisor, 然后搜索容器中所有的 bean ,
如果某个 bean 满足 advisor 中的 Pointcut, 那么将会被自动代理, 与 BeanNameAutoProxyCreator 相比, 省去了配置 beanNames 的工作,
引用:
eg :
- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
- <bean id="defaultPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" scope="prototype">
- <property name="pointcut" ref="fooPointcut"/>
- <property name="advice" ref="fooAdvice"/>
- </bean>
- <bean id="fooAdvice" class="com.mycompany.FooAdvice" scope="prototype" />
- <bean id="fooPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
- <property name="patterns">
- <list>
- <value>com.mycompany.FooService.*</value>
- </list>
- </property>
- </bean>
- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
- <bean id="defaultPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" scope="prototype">
- <property name="pointcut" ref="fooPointcut"/>
- <property name="advice" ref="fooAdvice"/>
- </bean>
- <bean id="fooAdvice" class="com.mycompany.FooAdvice" scope="prototype" />
- <bean id="fooPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
- <property name="patterns">
- <list>
- <value>com.mycompany.FooService.*</value>
- </list>
- </property>
- </bean>
以上配置将自动代理容器中所有 com.mycompany.FooService 类型的 bean, 并拦截其所有方法
深度话题
1. MethodInterceptor 如何被包装成 Advisor ?
在 AdvisorAdapterRegistry#wrap(Object) 方法中实现, code as below
- public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
- if (adviceObject instanceof Advisor) {
- return (Advisor) adviceObject;
- }
- if (!(adviceObject instanceof Advice)) {
- hrow new UnknownAdviceTypeException(adviceObject);
- }
- Advice advice = (Advice) adviceObject;
- if (advice instanceof MethodInterceptor) {
- // So well-known it doesn't even need an adapter.
- return new DefaultPointcutAdvisor(advice);
- }
- ; i < this.adapters.size(); i++) {
- / Check that it is supported.
- AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i);
- if (adapter.supportsAdvice(advice)) {
- return new DefaultPointcutAdvisor(advice);
- }
- }
- throw new UnknownAdviceTypeException(advice);
- }
- public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
- if (adviceObject instanceof Advisor) {
- return (Advisor) adviceObject;
- }
- if (!(adviceObject instanceof Advice)) {
- hrow new UnknownAdviceTypeException(adviceObject);
- }
- Advice advice = (Advice) adviceObject;
- if (advice instanceof MethodInterceptor) {
- // So well-known it doesn't even need an adapter.
- return new DefaultPointcutAdvisor(advice);
- }
- for (int i = 0; i < this.adapters.size(); i++) {
- / Check that it is supported.
- AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i);
- if (adapter.supportsAdvice(advice)) {
- return new DefaultPointcutAdvisor(advice);
- }
- }
- throw new UnknownAdviceTypeException(advice);
- }
从代码可以看到, 如果 adviceObject(也就是 interceptorNames 对应的 bean) 不是 advisor
而是 MethodInterceptor 或 Advice, 那么 spring 将其包装成 DefaultPointcutAdvisor,
而 DefaultPointcutAdvisor 中定义的 Pointcut 是 TruePointcut :
- class TruePointcut implements Pointcut, Serializable {
- public static final TruePointcut INSTANCE = new TruePointcut();
- /**
- * Enforce Singleton pattern.
- */
- private TruePointcut() {
- }
- public ClassFilter getClassFilter() {
- return ClassFilter.TRUE;
- }
- public MethodMatcher getMethodMatcher() {
- return MethodMatcher.TRUE;
- }
- /**
- * Required to support serialization. Replaces with canonical
- * instance on deserialization, protecting Singleton pattern.
- * Alternative to overriding <code>equals()</code>.
- */
- private Object readResolve() {
- return INSTANCE;
- }
- public String toString() {
- return "Pointcut.TRUE";
- }
- }
- class TruePointcut implements Pointcut, Serializable {
- public static final TruePointcut INSTANCE = new TruePointcut();
- /**
- * Enforce Singleton pattern.
- */
- private TruePointcut() {
- }
- public ClassFilter getClassFilter() {
- return ClassFilter.TRUE;
- }
- public MethodMatcher getMethodMatcher() {
- return MethodMatcher.TRUE;
- }
- /**
- * Required to support serialization. Replaces with canonical
- * instance on deserialization, protecting Singleton pattern.
- * Alternative to overriding <code>equals()</code>.
- */
- private Object readResolve() {
- return INSTANCE;
- }
- public String toString() {
- return "Pointcut.TRUE";
- }
- }
也就是说, MethodInterceptor 和 Advice 被包装成的 Advisor 将会匹配容器中的所有 bean,
所以, 永
远不要在 DefaultAdvisorAutoProxyCreator 的 interceptorNames 中引用一个 Advice,
那将会使容器中所有的 bean 被自动代理!!! 此时应该考虑使用 BeanNameAutoProxyCreator
Spring AOP 的proxy详解的更多相关文章
- Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现
前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的.本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所 ...
- Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建
上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...
- Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现
我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...
- Spring框架系列(12) - Spring AOP实现原理详解之JDK代理实现
上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分.@pdai Spring框架系列(12) - Spring AOP实现原理详解 ...
- Spring Aop底层原理详解
Spring Aop底层原理详解(来源于csdn:https://blog.csdn.net/baomw)
- Spring AOP 入门实例详解
目录 AOP概念 AOP核心概念 Spring对AOP的支持 基于Spring的AOP简单实现 基于Spring的AOP使用其他细节 AOP概念 AOP(Aspect Oriented Program ...
- Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...
- Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计
在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解.本文将帮助你站在设计者的角度去看IOC最顶层的结构设计.@pdai Spring框架系列(6) - Spring IOC实现原理详解 ...
- Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程
上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...
随机推荐
- VxWorks嵌入式系统几种常用的延时方法
1 taskDelay taskDelay(n)使调用该函数的任务延时n个tick(内核时钟周期).该任务在指定的时间内主动放弃CPU,除了taskDelay(0)专用 于任务调度(将CPU交 ...
- Naive Bayes (NB Model) 初识
1,Bayes定理 P(A,B)=P(A|B)P(B); P(A,B)=P(B|A)P(A); P(A|B)=P(B|A)P(A)/P(B); 贝叶斯定理变形 2,概率图模型 2.1 定义 概 ...
- javaWeb之eclipse创建Servlet模板快捷键设置
没有模板创建Servlet 出现的是除了doPOST 和doGet方法 还有许多方法和一些注释,页面不够清晰 创建模板的步骤是: 1.点击window下的preference 选项 2在 表单框里填写 ...
- 物联网框架ServerSuperIO在.NetCore实现跨平台的实践路线
正所谓天下大势,不跟风不行.你不跨平台,很low嘛.java说:你们能跨嘛,跨给我看看.C#说:不要强人所难嘛.java说:能部署在云上吗?docker?微服务?C#说:不要强人所难嘛.java说:你 ...
- VS2010编译VS2008工程时,LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt
1.问题 电脑上同时安装了VS2008,VS2010,使用VS2010编译VS2008建立的工程,或者,VS2010创建新的工程.编译时,出现以下链接错误: LINK : fatal error LN ...
- Python编程核心内容之二——切片、迭代和列表生成式
Python版本:3.6.2 操作系统:Windows 作者:SmallWZQ 最近太忙啦.很多事情需要自己处理,感觉时间不够用啊~~~~今后,博客更新时间可能会慢下来,哈哈,正所谓"人 ...
- (luogu4180) [Beijing2010组队]次小生成树Tree
严格次小生成树 首先看看如果不严格我们怎么办. 非严格次小生成树怎么做 由此,我们发现一个结论,求非严格次小生成树,只需要先用kruskal算法求得最小生成树,然后暴力枚举非树边,替换路径最大边即可. ...
- Poj3678:Katu Puzzle
大概题意 有\(n\)个数,可以为\(0/1\),给\(m\)个条件,表示某两个数经过\(or, and, xor\)后的数是多少 判断是否有解 Sol \(2-SAT\)判定 建图 # includ ...
- [BZOJ1878] [SDOI2009] HH的项链 (树状数组)
Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变 ...
- (python走过的坑)OpenCV中错误opencv-3.3.1\modules\highgui\src\window.cpp:339: error: (-215) size.width>0 && size.height>0 in function cv::imshow
第一次在python中使用OpenCV(cv2),运行时报错opencv-3.3.1\modules\highgui\src\window.cpp:339: error: (-215) size.wi ...