转发地址:https://www.iteye.com/blog/elim-2397922

编程式的创建Aop代理之AspectjProxyFactory

之前已经介绍了一款编程式的创建Aop代理的工厂——ProxyFactory,其实ProxyFactory拥有的功能AspectjProxyFactory都有。它们虽然没有直接的继承关系,但是它们都继承自ProxyCreatorSupport,而创建代理对象的核心逻辑都是在ProxyCreatorSupport中实现的。所以说ProxyFactory拥有的功能AspectjProxyFactory都有。那么AspectjProxyFactoryProxyFactory相比有什么不同呢?
AspectjProxyFactory的特殊之处就在于其可以直接指定需要创建的代理对象需要绑定的切面。在使用ProxyFactory时,我们能够绑定的是AdvisorAdvice,但是如果我们的程序中已经有了现成的切面类定义且能够为我们新创建的代理类使用时,我们还要为了ProxyFactory建立代理对象的需要创建对应的Advisor类、Advice类和Pointcut类定义,这无疑是非常麻烦的。AspectjProxyFactory通常用于创建基于Aspectj风格的Aop代理对象。现假设我们有如下这样一个切面类定义。

@Aspect
public class MyAspect { @Pointcut("execution(* add(..))")
private void beforeAdd() {} @Before("beforeAdd()")
public void before1() {
System.out.println("-----------before-----------");
} }

在上述切面类定义中我们定义了一个Advisor,其对应了一个BeforeAdvice,实际上是一个AspectJMethodBeforeAdvice,该Advice对应的是上面的before1()方法,还对应了一个Pointcut,实际上是一个AspectJExpressionPointcut。该Advisor的语义就是调用所有的方法名为“add”的方法时都将在调用前调用MyAspect.before1()方法。如果我们现在需要创建一个代理对象,其需要绑定的Advisor逻辑跟上面定义的切面类中定义的Advisor类似。则我们可以进行如下编程。

@Test
public void testAspectJProxyFactory() {
MyService myService = new MyService();
AspectJProxyFactory proxyFactory = new AspectJProxyFactory(myService);
proxyFactory.addAspect(MyAspect.class);
proxyFactory.setProxyTargetClass(true);//是否需要使用CGLIB代理
MyService proxy = proxyFactory.getProxy();
proxy.add();
}

在上述代码中我们AspectjProxyFactory在创建代理对象时需要使用的切面类(其实addAspect还有一个重载的方法可以指定一个切面类的对象),其实在AspectjProxyFactory内部还是解析了该切面类中包含的所有的Advisor,然后把能够匹配当前代理对象类的Advisor与创建的代理对象绑定了。有兴趣的读者可以查看一下AspectjProxyFactory的源码,以下是部分核心代码。

public void addAspect(Class<?> aspectClass) {
String aspectName = aspectClass.getName();
AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
MetadataAwareAspectInstanceFactory instanceFactory =
createAspectInstanceFactory(am, aspectClass, aspectName);
addAdvisorsFromAspectInstanceFactory(instanceFactory);
} private void addAdvisorsFromAspectInstanceFactory(
MetadataAwareAspectInstanceFactory instanceFactory) {
List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
OrderComparator.sort(advisors);
addAdvisors(advisors);
}

需要注意的是在使用AspectjProxyFactory基于切面类创建代理对象时,我们指定的切面类上必须包含@Aspect注解。
另外需要注意的是虽然我们自己通过编程的方式可以通过AspectjProxyFactory创建基于@Aspect标注的切面类的代理,但是通过配置<aop:aspectj-autoproxy/>使用基于注解的Aspectj风格的Aop时,Spring内部不是通过AspectjProxyFactory创建的代理对象,而是通过ProxyFactory。有兴趣的朋友可以查看一下AnnotationAwareAspectjAutoProxyCreator的源代码。

(注:本文是基于Spring4.1.0所写,Elim写于2017年5月9日)

Spring Aop(十二)——编程式的创建Aop代理之AspectjProxyFactory的更多相关文章

  1. Spring Aop(十一)——编程式的创建Aop代理之ProxyFactory

    转发地址:https://www.iteye.com/blog/elim-2397388 编程式的创建Aop代理之ProxyFactory Spring Aop是基于代理的,ProxyFactory是 ...

  2. Spring Boot(十二):spring boot如何测试打包部署

    Spring Boot(十二):spring boot如何测试打包部署 一.开发阶段 1,单元测试 在开发阶段的时候最重要的是单元测试了,springboot对单元测试的支持已经很完善了. (1)在p ...

  3. VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池

    VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池 在上一节我们创建了完整克隆的自动专有桌面池,在创建过程比较缓慢,这次我们将学习创建Vi ...

  4. Spring Aop(十)——编程式的Pointcut

    转发地址:https://www.iteye.com/blog/elim-2396526 编程式的Pointcut 除了可以通过注解和Xml配置定义Pointcut之外,其实我们还可以通过程序来定义P ...

  5. Spring框架——事务处理(编程式和声明式)

     一. 事务概述 ●在JavaEE企业级开发的应用领域,为了保证数据的完整性和一致性,必须引入数据库事务的概念,所以事务管理是企业级应用程序开发中必不可少的技术. ●事务就是一组由于逻辑上紧密关联而合 ...

  6. Spring事务管理之编程式事务管理

    © 版权声明:本文为博主原创文章,转载请注明出处 案例:利用Spring的编程式事务管理模拟转账过程 数据库准备 -- 创建表 CREATE TABLE `account`( `id` INT NOT ...

  7. spring学习总结二-----面向切面编程(AOP)思想

    上一篇spring博客简总结了spring控制反转和依赖注入的相关思想知识点,这篇博文对spring的面向切的编程思想进行简单的梳理和总结. 一.面向切面的思想 与面向对象的纵向关系概念不同,面向切面 ...

  8. Spring(十二)Spring之事务

    java中事务是什么? 事务是访问数据库的一个操作序列,DB应用系统通过事务集来完成对数据的存取. 事务必须遵循4个原则,即常说的 ACID A,Automicity,原子性,即事务要么被全部执行,要 ...

  9. (转)Spring Boot(十二):Spring Boot 如何测试打包部署

    http://www.ityouknow.com/springboot/2017/05/09/spring-boot-deploy.html 有很多网友会时不时的问我, Spring Boot 项目如 ...

随机推荐

  1. 4.使用webpack-dev-server工具实现自动打包编译的功能

    使用webpack-dev-server这个工具,来实现自动打包编译的功能 1.运行 npm i webpack-dev-server -D 把这个工具安装到项目的本地开发依赖 或者运行 cnpm i ...

  2. 系统分析与设计结对项目——WordCount

    结对项目完成WordCount 合作者:201631062507  201631062526(学号) 代码地址:https://gitee.com/WordCountMC/WordCountTeam ...

  3. SQLCommand命令、DbTransaction事务

    一.SqlDataReader SqlConnection conn = new SqlConnection("server=10.126.64.11;user=it_oper;pwd=IT ...

  4. Oracle 后台进程(二)DBWR进程

    一.DBWR进程介绍 DBWR进程执行将数据块缓冲区写入数据文件的工作,是负责缓冲存储管理的一个Oracle后台进程.在修改DB Cache中的某个缓冲区时,会将它标志为“DIRTY”,DBWR的主要 ...

  5. CF 940F - Machine Learning ( 带 修 )

    题目: 链接:https://codeforces.com/problemset/problem/940/F 题意:给你n个数,a[i]有q个操作,操作有两种:操作1.       1 x y 表示询 ...

  6. [Poj] Roads in the North

    http://poj.org/problem?id=2631 树的直径裸题 dfs/bfs均可 /* dfs */ #include <iostream> #include <cst ...

  7. .net Core使用 MongoDB

    1.安装mogodb windows版本下载地址:https://www.mongodb.com/download-center/v2/community 查看mongod.conf文件,找到绑定的I ...

  8. 7月清北学堂培训 Day 6

    今天是钟皓曦老师的讲授~ 合并石子拓展: 合并任意两堆石子,每次合并的代价是这两堆石子的重量的异或值,求合并成一堆的最小异或和. 状态设置:f [ s ] 把 s 所对应的石子合并的最小代价: 那么答 ...

  9. leveldb源码分析之内存池Arena

    转自:http://luodw.cc/2015/10/15/leveldb-04/ 这篇博客主要讲解下leveldb内存池,内存池很多地方都有用到,像linux内核也有个内存池.内存池的存在主要就是减 ...

  10. codeforces#101194H. Great Cells(数学)

    题目链接: https://codeforces.com/gym/101194 题意: 在$n×m$的各自中填上$1$到$k$的数 定义Greate cell为严格大于同行和同列的格子 定义$A_g$ ...