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采用基于类的代理。除此之外,如果将ProxyFactoryoptimize属性设为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类型)、exposeProxyfrozen

要生成代理对象,光有ProxyConfig提供的控制信息还不够,我们还需要生成代理对象的一些具体信息,比如Jointpoint和Advice,这些信息可以通过实现Advised接口来设置或者查询(addAdvisor()/removeAdvisor())。

那么,AopProxyAdvisedSupportProxyFactory是什么关系呢?

ProxyFactoryAopProxyAdvisedSupport于一身,所以可以通过它设置生成对象所需要的相关信息,也可以通过它取得最终生成的代理对象。前者是AdvisedSupport的职责,后者是AopProxy的职责。

至此,我们已经了解了ProxyFactory这个最基本的织入器实现,它还有几个兄弟,比如AspectJProxyFactoryProxyFactoryBean,它们的关系如下所示,在此不作进一步说明,有兴趣的读者可以查阅《Spring揭秘》P179。

参考资料:《Spring揭秘》王福强

Spring中的AOP(二)的更多相关文章

  1. spring中的AOP 以及各种通知 配置

    理解了前面动态代理对象的原理之后,其实还是有很多不足之处,因为如果在项目中有20多个类,每个类有100多个方法都需要判断是不是要开事务,那么方法调用那里会相当麻烦. spring中的AOP很好地解决了 ...

  2. Spring学习笔记(四)—— Spring中的AOP

    一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...

  3. 2018.12.24 Spring中的aop演示(也就是运用aop技术实现代理模式)

    Aop的最大意义是:在不改变原来代码的前提下,也不对源代码做任何协议接口要求.而实现了类似插件的方式,来修改源代码,给源代码插入新的执行代码. 1.spring中的aop演示 aop:面向方面编程.不 ...

  4. (五)Spring 中的 aop

    目录 文章目录 AOP概念 AOP原理 AOP术语 **`Spring`** 中的 **`aop`** 的操作 使用 `AspectJ` 实现 `aop` 的两种方式 AOP概念 浅理解 aop :面 ...

  5. Spring中的AOP

    什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...

  6. Spring中关于AOP的实践之概念

    一.什么是AOP AOP:也称作面向切面编程 在分享几个概念执行我想先举个栗子(可能例子举得并不是特别恰当): 1.假如路人A走在大街上,被一群坏人绑架了: 2.警察叔叔接到报警迅速展开行动:收集情报 ...

  7. Spring中的AOP 专题

    Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...

  8. JavaWeb_(Spring框架)认识Spring中的aop

    1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...

  9. Spring 中基于 AOP 的 @AspectJ

    Spring 中基于 AOP 的 @AspectJ @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格. 通过在你的基于架构的 XML ...

  10. Spring 中基于 AOP 的 XML架构

    Spring 中基于 AOP 的 XML架构 为了使用 aop 命名空间标签,你需要导入 spring-aop j架构,如下所述: <?xml version="1.0" e ...

随机推荐

  1. 读Pyqt4教程,带你入门Pyqt4 _005

    对话框窗体或对话框是现代GUI应用不可或缺的一部分.dialog定义为两个或多个人之间的交谈.在计算机程序中dialog是一个窗体,用来和程序“交谈”.对话框用来输入数据.修改数据.改变程序设置等等. ...

  2. 慕零的黑夜-头条-第一期(必问)[导读:]1.CSDN必问赏金流向何方 2.CSDN必问偷偷做的手脚 3.CSDN必问靠谱吗 4.关于钱于回答的平衡问题:一美元拍卖骗局 作者:qq3461896724

    本期是关于CSDN 必问 (biwen.csdn.net)的内容,欢迎评论 文末,文中插入有 小姐姐 img(附py代码,1.49G) + coding资料 哟~~~ 你看到这篇很可能是在提问.推荐加 ...

  3. Activity组件暴露导致本地拒绝服务

    这几天团队打算一起学习Android App漏洞挖掘方面的知识,于是乎拿了一个app当测试例子,争取在上面找到漏洞.在学习过程中发现Android四大组件的安全性还是占有较大的比重,另外比较关心的是数 ...

  4. Rocket - tilelink - Bundles

    https://mp.weixin.qq.com/s/jrqBg2AIpQogBrpwNXjmwg   简单介绍Bundles文件中对TileLink规范(1.7.1)的定义. 参考链接:https: ...

  5. Java实现 LeetCode 811 子域名访问计数 (暴力)

    811. 子域名访问计数 一个网站域名,如"discuss.leetcode.com",包含了多个子域名.作为顶级域名,常用的有"com",下一级则有" ...

  6. 第十届蓝桥杯JavaC组省赛真题

    试题 A: 求和 本题总分:5 分 [问题描述] 小明对数位中含有 2.0.1.9 的数字很感兴趣,在 1 到 40 中这样的数包 括 1.2.9.10 至 32.39 和 40,共 28 个,他们的 ...

  7. Java实现 LeetCode 54 螺旋矩阵

    54. 螺旋矩阵 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素. 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], ...

  8. java关键字static用法详解

    java中有53个关键字,其中包含2个保留字,这篇文章主要介绍一下static这个关键字. static在java中算是一个比较常见的关键字,有着多种用法,因此很有必要好好地了解一番. 一.定义 st ...

  9. Linux系统命令详解

    目录 1. su 1.1. su命令中passwd的自动输入 2. sshpass 3. locate/mlocate 4. top/htop 5. lftp 6. kill/killall 1. s ...

  10. (五)连接查询(SQL99标准)、子查询、分页查询、联合查询

    一.连接查询(SQL99标准) 1.含义:当要查询的数据来自多张表时要使用连接查询 2.语法: select 查询列表 from 表1 别名 [连接类型] join 表2 别名 on 连接条件 [wh ...