Spring中的AOP(二)
2.5 Spring的织入
在上一篇文章中,我们介绍了Pointcut、Advice、Advisor三个必要模块,剩下的工作就是把它们拼装起来,也就是织入过程。在Spring中,使用类org.springframework.aop.framework.ProxyFactory作为织入器。
2.5.1 认识ProxyFactory
首先,ProxyFactory并非Spring AOP中唯一可用的织入器,而是最基本的一个织入器实现。所以,我们就从这个最基本的织入器开始,了解一下织入过程到底是什么样子的。
使用ProxyFactory进行织入的逻辑很简单,只要为它提供生产代理对象的原材料,它就会返回那个织入完成的代理对象。我们来看示例代码:
ProxyFactory weaver = new ProxyFactory(yourTargetObject);
Advisor advisor = ...;
weaver.addAdvisor(advisor);
Object proxyObject = weaver.getProxy();
我们知道,Spring AOP在使用代理模式实现AOP的过程中采用了动态代理和CGLIB两种机制,分别对某些接口的目标类和没有实现任何接口的目标类进行代理,所以在使用ProxyFactory对目标类进行代理的时候,会通过ProxyFactory的某些行为控制属性对这两种情况进行区分。我们来看具体的场景,首先我们有一个接口,以及它的一个实现类:
public interface ITask {
void execute(TaskExecutionContext ctx);
}
public class MockTask implements ITask {
public void execute(TaskExecutionContext ctx) {
System.out.println("task execute.");
}
}
另外,我们还需要一个织入到Jointpoint的一个横切逻辑,也就是Advice实现。假设是PerformanceMethodInterceptor:
// 简单的检测系统某些方法的执行性能
public class PerformanceMethodInterceptor implements MethodInterceptor {
private final Log logger = LogFactory.getLog(this.getClass());
public Object invoke(MethodInvocation invocation) throws Throwable {
StopWatch watch = new StopWatch();
try {
watch.start();
return invocation.proceed();
} catch (Exception e) {
//TODO: handle exception
} finally {
watch.stop();
if (logger.isInfoEnabled()) {
logger.info(watch.toString());
}
}
}
}
- 基于接口的代理:
MockTask实现了ITask接口,要对这种实现了某些接口的目标类进行代理,我们使用setInterfaces(new Class[]{ITask.class})来明确告知ProxyFactory我们要对ITask接口类型进行代理。
ProxyFactory weaver = new ProxyFactory(new MockTask);
weaver.setInterfaces(new Class[]{ITask.class});
- 基于类的代理:如果目标类没有实现任何接口,
ProxyFactory会对目标类型进行基于类的代理,即使用CGLIB。假设我们现在有一个对象,定义如下:
public class Executable {
public void execute() {
System.out.println("Executable without any Interfaces");
}
}
织入的过程如下所示:
ProxyFactory weaver = new ProxyFactory(new Executable());
weaver.addAdvisor(advisor);
Executable proxyObject = (Executable)weaver.getProxy();
proxyObject.execute();
但是,即使目标对象类实现了至少一个接口,我们也可以通过proxyTargetClass属性强制ProxyFactory采用基于类的代理。除此之外,如果将ProxyFactory的optimize属性设为true的话,也会采用基于类的代理机制。
2.5.2 看清ProxyFactory的本质
我们不仅要知晓怎么使用ProxyFactory,并且还需要了解它其中的内部实现,这可以帮我们更好地使用它。我们先从它的根说起:
public interface AopProxy {
Object getProxy();
Object getProxy(ClassLoader classLoader)
}
这个接口对Spring AOP框架内的不同代理实现机制做了适度的抽象,目前,Spring提供了基于JDK动态代理和CGLIB两种机制的AopProxy实现。

首先,我们来看工厂类AopProxyFactory的定义:
public interface AopProxyFactory {
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
AopProxyFactory的实现类就一个,DefaultAopProxyFactory,它会根据传入的AdvisedSupport示例提供的相关信息,来决定生成什么类型的AopProxy,实现逻辑很简单,伪代码如下:
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 创建Cglib2AopProxy实例,并返回
} else {
// 创建JdkDynamicAopProxy实例,并返回
}
可以发现,生成的AopProxy类型是由AdvisedSupport实例来决定的,我们来看一下这个类到底是何方神圣。

AdvisedSupport继承了ProxyConfig类并实现了Advised接口。我们先来看ProxyConfig类,它其实就是个普通的JavaBean,它定义了5个boolean类型的属性,分别为proxyTargetClass(指定是否使用CGLIB代理)、optimize(告知代理对象是否要进行进一步优化,若为true,则使用CGLIB,默认为false)、opaque(控制代理对象是否可以强制转为Advised类型)、exposeProxy、frozen。
要生成代理对象,光有ProxyConfig提供的控制信息还不够,我们还需要生成代理对象的一些具体信息,比如Jointpoint和Advice,这些信息可以通过实现Advised接口来设置或者查询(addAdvisor()/removeAdvisor())。
那么,AopProxy、AdvisedSupport与ProxyFactory是什么关系呢?

ProxyFactory集AopProxy和AdvisedSupport于一身,所以可以通过它设置生成对象所需要的相关信息,也可以通过它取得最终生成的代理对象。前者是AdvisedSupport的职责,后者是AopProxy的职责。
至此,我们已经了解了ProxyFactory这个最基本的织入器实现,它还有几个兄弟,比如AspectJProxyFactory和ProxyFactoryBean,它们的关系如下所示,在此不作进一步说明,有兴趣的读者可以查阅《Spring揭秘》P179。

参考资料:《Spring揭秘》王福强
Spring中的AOP(二)的更多相关文章
- spring中的AOP 以及各种通知 配置
理解了前面动态代理对象的原理之后,其实还是有很多不足之处,因为如果在项目中有20多个类,每个类有100多个方法都需要判断是不是要开事务,那么方法调用那里会相当麻烦. spring中的AOP很好地解决了 ...
- Spring学习笔记(四)—— Spring中的AOP
一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...
- 2018.12.24 Spring中的aop演示(也就是运用aop技术实现代理模式)
Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 1.spring中的aop演示 aop:面向方面编程.不 ...
- (五)Spring 中的 aop
目录 文章目录 AOP概念 AOP原理 AOP术语 **`Spring`** 中的 **`aop`** 的操作 使用 `AspectJ` 实现 `aop` 的两种方式 AOP概念 浅理解 aop :面 ...
- Spring中的AOP
什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...
- Spring中关于AOP的实践之概念
一.什么是AOP AOP:也称作面向切面编程 在分享几个概念执行我想先举个栗子(可能例子举得并不是特别恰当): 1.假如路人A走在大街上,被一群坏人绑架了: 2.警察叔叔接到报警迅速展开行动:收集情报 ...
- Spring中的AOP 专题
Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...
- JavaWeb_(Spring框架)认识Spring中的aop
1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...
- Spring 中基于 AOP 的 @AspectJ
Spring 中基于 AOP 的 @AspectJ @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格. 通过在你的基于架构的 XML ...
- Spring 中基于 AOP 的 XML架构
Spring 中基于 AOP 的 XML架构 为了使用 aop 命名空间标签,你需要导入 spring-aop j架构,如下所述: <?xml version="1.0" e ...
随机推荐
- sqlmap基本使用
sqlmap 使用 需要安装python2的环境 使用方法: 用最基础的get型注入开始 1.当我们发现注入点的时候, python sqlmap.py -u "http://192.168 ...
- 【docker系列2】docker 的前世今生
Docker 入门,共 3 篇,将带大家进入 Docker 的世界.首先了解 Docker 的发展历程, 然后快速掌握 Docker 的基本使用: Docker 版本及内核兼容性选择是这部分的重点内容 ...
- 使用RTL进行硬件模型编程的局限性
https://mp.weixin.qq.com/s/Nj_d3hwgNX4kWVtKsqMSWg 硬件模型编程,即Hardware Model Programming.在RTL抽象级别 ...
- DOM、事件面试题
1.DOM 事件级别有哪些? DOM0 a. 通过定义执行函数 element.onclick = function (){ } b. 直接在标签中添加执行语句 Onclick = '语句' 优点:很 ...
- MethodHandle(方法句柄)系列之二:方法句柄的简单使用
二话不说,上代码 /** * * @author LiuYeFeng<897908343@qq.com> * @date 2015年4月8日 下午10:41:13 * @CopyRigh ...
- Java实现 蓝桥杯VIP 算法提高 淘淘的名单
算法提高 淘淘的名单 时间限制:100ms 内存限制:8.0MB 问题描述 by ZBY- ? 淘淘拿到了一份名单,他想对上面的名字进行处理,挑出一些特殊的名字,他请你来帮忙. 淘淘关注以下名字: 如 ...
- Java实现 蓝桥杯 算法训练 字符串合并
试题 算法训练 字符串合并 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输入两个字符串,将其合并为一个字符串后输出. 输入格式 输入两个字符串 输出格式 输出合并后的字符串 样例 ...
- Java中map.getOrDefault()方法的使用
Map.getOrDefault(Object key, V defaultValue)方法的作用是: 当Map集合中有这个key时,就使用这个key值: 如果没有就使用默认值defaultV ...
- Java实现字符串的包含
1 问题描述 给定一长字符串A和一短字符串B.请问,如何最快地判断出短字符串B中的所有字符是否都在长字符串A中?请编写一个判断函数实现此功能. 为简单起见,假设输入的字符串只包含小写英文字母.下面举几 ...
- java实现第六届蓝桥杯九数组分数
九数组分数 九数组分数 1,2,3...9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码. public class A { public s ...