转发地址: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. bat 判断 bat 是否是以管理员权限运行,和自动以管理员权限运行

    bat 判断 bat 是否是以管理员权限运行,和自动以管理员权限运行 判断 @echo off net.exe session 1>NUL 2>NUL && ( goto ...

  2. python_网络编程socket(UDP)

    服务端: import socket sk = socket.socket(type=socket.SOCK_DGRAM) #创建基于UDP协议的socket对象 sk.bind(('127.0.0. ...

  3. Java集合--Map总结

    转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3311126 第1部分 Map概括 (01) Map ...

  4. vue slot及用法,$slots访问具名slot

  5. win10笔记本连接wifi出现:您的计算机配置似乎是正确的,但该配置或资源(DNS服务器)检测到有响应

    问题上图: 一直以来连接网线使用,很少使用WiFi了,在网线不好使的时候使用wifi发现并不怎么好用,甚至上不了网页,但是那时候也不怎么在意,不过一会网线就好使了所以也没处理,直到今天,因为接下来好多 ...

  6. BZOJ3122 随机数生成器——BSGS

    题意 链接 给定 $p,\ a,\ b, \ x_1$,现有一数列 $$x_{i+1} \equiv (ax_i + b) \ mod \ p$$ 求最小的 $i$ 满足 $x_i = t$ 分析 代 ...

  7. Linq to JSON/Json.NET

    Can I LINQ a JSON? http://stackoverflow.com/questions/18758361/can-i-linq-a-json Json.NET https://js ...

  8. 把Cstring类型的字符串转化为char* 字符串;

    int char_leng; Cstring str="abcd"; char_leng=str.GetLength();//获取字符串长度 char *str_temp=(cha ...

  9. c++ 生成容器元素生成随机数

    // random_shuffle example #include <iostream> // cout #include <algorithm> // random_shu ...

  10. java试题复盘——9月26日

    5.在 JAVA 编程中, Java 编译器会将 Java 程序转换为(A) A.  字节码 B.  可执行代码 C.  机器代码 D.  以上都不对 解析: 编译器将Java源代码编译成字节码cla ...