Java AOP知识详细介绍

Java AOP

AOP知识整理

AOP(Aspect-Oriented Programming):面向切面的编程。OOP(Object-Oriented Programming)面向对象的编程。对于OOP我们已经再熟悉不过了,对于AOP,可能我们会觉得是一种新特性,其实AOP是对OOP的一种补充,OOP面向的是纵向编程,继承、封装、多态是其三大特性,而AOP是面向横向的编程。

面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足。在OOP中模块化的关键单元是类(classes),而在AOP中模块化的单元则是切面。切面能对关注点进行模块化,例如横切多个类型和对象的事务管理。
AOP框架是spring的一个重要组成部分。但是Spring IoC容器并不依赖于AOP,这意味着你有权利选择是否使用AOP,AOP做为Spring IoC容器的一个补充,使它成为一个强大的中间件解决方案。

AOP在Spring Framework中的作用

  • 提供声明式企业服务,特别是为了替代EJB声明式服务。最重要的服务是声明性事务管理(这个我想是AOP使用最多的一处了)。
  • 允许用户实现自定义切面,用AOP来完善OOP的使用。

1.AOP概念:

学习AOP,当然得先了解一下其众多的概念性术语:

  • 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式)或者基于@Aspect注解的方式来实现。
  • 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。
  • 通知(Advice):在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知(通知的类型将在后面部分进行讨论)。许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。
  • 切入点(Pointcut):匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
  • 引入(Introduction):用来给一个类型声明额外的方法或属性(也被称为连接类型声明(inter-type declaration))。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用引入来使一个bean实现IsModified接口,以便简化缓存机制。
  • 目标对象(Target Object): 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。
  • AOP代理(AOP Proxy):AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
  • 织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

通知类型:

  • 前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
  • 后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
  • 异常通知(After throwing advice):在方法抛出异常退出时执行的通知。
  • 最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。

环绕通知是最常用的通知类型。和AspectJ一样,Spring提供所有类型的通知,我们推荐你使用尽可能简单的通知类型来实现需要的功能。例如,如果你只是需要一个方法的返回值来更新缓存,最好使用后置通知而不是环绕通知,尽管环绕通知也能完成同样的事情。用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误。比如,你不需要在JoinPoint上

调用用于环绕通知的proceed()方法,就不会有调用的问题。

在这里,基于@AspectJ的AOP我就不多写了,因为我更青睐于Spring中使用ProxyFactoryBean创建AOP代理。

2.使用ProxyFactoryBean创建AOP代理:

在Spring里创建一个AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean。 这个类对应用的切入点和通知提供了完整的控制能力(包括它们的应用顺序)。像其它的FactoryBean实现一样,ProxyFactoryBean引入了一个间接层。如果你定义一个名为foo的ProxyFactoryBean, 引用foo的对象看到的将不是ProxyFactoryBean实例本身,而是一个ProxyFactoryBean实现里getObject() 方法所创建的对象。 这个方法将创建一个AOP代理,它包装了一个目标对象。

ProxyFactoryBean类本身也是一个JavaBean,其属性主要有如下用途:

  • 指定你希望代理的目标对象
  • 指定是否使用CGLIB。

一些主要属性从org.springframework.aop.framework.ProxyConfig里继承下来(这个类是Spring里所有AOP代理工厂的父类)。这些主要属性包括:

  • proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建。
  • optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略。 除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB代理; 对于JDK动态代理(缺省代理)无效。
  • frozen:如果一个代理配置是frozen的,就不允许对该配置进行修改。 这在简单优化和不希望调用者在代理创建后操作代理(通过Advised接口) 时很有用。缺省值为false,即可以进行类似添加附加通知的操作。
  • exposeProxy:决定当前代理是否被暴露在一个ThreadLocal 中以便被目标对象访问。如果目标对象需要获取代理而且exposeProxy属性被设为 true,目标对象可以使用AopContext.currentProxy()方法。
  • aopProxyFactory:使用AopProxyFactory的实现。这提供了一种方法来自定义是否使用动态代理,CGLIB或其它代理策略。 缺省实现将根据情况选择动态代理或者CGLIB。一般情况下应该没有使用这个属性的需要;它是被设计来在Spring 1.1中添加新的代理类型的。

ProxyFactoryBean中需要说明的其它属性包括:

  • proxyInterfaces:需要代理的接口名的字符串数组。 如果没有提供,将为目标类使用一个CGLIB代理。
  • interceptorNames:Advisor的字符串数组,可以包括拦截器或其它通知的名字。 顺序是很重要的,排在前面的将被优先服务。就是说列表里的第一个拦截器将能够第一个拦截调用。

这里的名字是当前工厂中bean的名字,包括父工厂中bean的名字。这里你不能使用bean的引用因为这会导致ProxyFactoryBean忽略通知的单例设置。
你可以把一个拦截器的名字加上一个星号作为后缀(*)。这将导致这个应用程序里所有名字以星号之前部分开头的通知器都被应用。

单例:工厂是否应该返回同一个对象,不论方法getObject()被调用的多频繁。 多个FactoryBean实现都提供了这个方法。缺省值是true。 如果你希望使用有状态的通知--例如,有状态的mixin--可以把单例属性的值设置为false来使用原型通知。

3.基于JDK和CGLIB的代理:

如果一个需要被代理的目标对象的类(后面将简单地称它为目标类)没有实现任何接口,那么一个基于CGLIB的代理将被创建。 这是最简单的场景,因为JDK代理是基于接口的,没有接口意味着没有使用JDK进行代理的可能.

如果ProxyFactoryBean的proxyTargetClass属性被设为true,那么一个基于CGLIB的代理将创建。 这样的规定是有意义的,遵循了最小惊讶法则(保证了设定的一致性)。甚至当ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名, 而proxyTargetClass属性被设置为true仍然将实际使用基于CGLIB的代理。

如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,一个基于JDK的代理将被创建。 被创建的代理将实现所有在proxyInterfaces属性里被说明的接口; 如果目标类实现了全部在proxyInterfaces属性里说明的接口以及一些额外接口,返回的代理将只实现说明的接口而不会实现那些额外接口。

如果ProxyFactoryBean的proxyInterfaces属性没有被设置, 但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口, 一个基于JDK的代理将被创建。被实际代理的接口将是目标类所实现的全部接口; 实际上,这和在proxyInterfaces属性中列出目标类实现的每个接口的情况是一样的。 然而,这将显著地减少工作量以及输入错误的可能性。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Java的Spring框架中AOP项目的一般配置和部署教程

    0.关于AOP 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个重要内容.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. AOP是OOP的延续. 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等. 主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过

  • 实例讲解Java的Spring框架中的AOP实现

    简介 面向切面编程(AOP)提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足. 除了类(classes)以外,AOP提供了 切面.切面对关注点进行模块化,例如横切多个类型和对象的事务管理. (这些关注点术语通常称作 横切(crosscutting) 关注点.) Spring的一个关键的组件就是 AOP框架. 尽管如此,Spring IoC容器并不依赖于AOP,这意味着你可以自由选择是否使用AOP,AOP提供强大的中间件解决方案,这使得Spring IoC容器更加完善

  • Java之Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就算这样,但你肯定也会有后台管理及登录功能. 每个项目中都会有这些几乎一样的业务逻辑,我们能不能把他们做成通用的系统呢? AOP 实现用户权限验证 AOP 在实际项目中运用的场景主要有权限管理(Authority Management).事务管理(Transaction Management).安全管

  • Java动态代理实现AOP

    目前整个开发社区对AOP(Aspect Oriented Programing)推崇备至,也涌现出大量支持AOP的优秀Framework,--Spring, JAC, Jboss AOP 等等.AOP似乎一时之间成了潮流.Java初学者不禁要发出感慨,OOP还没有学通呢,又来AOP.本文不是要在理论上具体阐述何为AOP, 为何要进行AOP . 要详细了解学习AOP可以到它老家http://aosd.net去瞧瞧.这里只是意图通过一个简单的例子向初学者展示一下如何来进行AOP. 为了简单起见,例子

  • 详解使用Java原生代理实现AOP实例

    一说到AOP,大家一定会想到spring,因为这东西实在是太强大了.但是大家一定要清楚,AOP是一只编程思想,而Spring仅仅是AOP的一种实现罢了. 首先百度下: 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务

  • Java的Spring框架下的AOP编程模式示例

    Spring框架的关键组件是面向方面编程(AOP)框架.面向方面的编程不仅打破程序逻辑分成不同的部分称为所谓的担忧.跨越多个点的应用程序的功能被称为横切关注点和这些横切关注点是从应用程序的业务逻辑概念上区分开来.还有像日志记录,审计,声明性事务,安全性和高速缓存等方面的各种常见的好例子 模块化的OOP中的关键单元是类,而在AOP中模块化的单元则是切面.依赖注入可以帮助你从对方解耦应用程序对象和AOP可以帮助你从他们影响的对象分离横切关注点. AOP是一样的编程语言如Perl,.NET,Java和

  • 详解Java反射实现Aop代理

    利用反射生成JDK的动态代理,也就是AOP中的AOP代理,代替目标对象,从而在代码中织入增强. 定义代理接口 由于JDKf动态代理只能为接口创建动态代理,故先定义接口,假定我们需要对数据的Save方法添加事务处理,我们有一个UserDao接口,里面有一个Save方法,代码如下: public interface UserDao { public void save(); } 定义代理实现 下面具体来实现接口定义的Save方法,我们采用下面的代码来实现. public class UserDaoI

  • 举例讲解Java的Spring框架中AOP程序设计方式的使用

    1.什么是AOP AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,AOP实际是GoF设计模式的延续. 2.关于Spring AOP的一些术语:  A.切面(Aspect):在Spring AOP中,切面可以使用通用类或者在普通类中以@Aspect 注解(@AspectJ风格)来实现 B.连接点(Joinpoint):在Spring AOP中一个连接点代表一个方法的执行 C.通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作.

  • java基于spring注解AOP的异常处理的方法

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...finally对异常进行处理,但是我们真的能在写程序的时候处理掉所有可能发生的异常吗? 以及发生异常的时候执行什么逻辑,返回什么提示信息,跳转到什么页面,这些都是要考虑到的. 二.基于@ControllerAdvice(加强的控制器)的异常处理 @ControllerAdvice注解内部使用@Except

  • Java实现AOP面向切面编程的实例教程

    介绍 众所周知,AOP(面向切面编程)是Spring框架的特色功能之一.通过设置横切关注点(cross cutting concerns),AOP提供了极高的扩展性.那AOP在Spring中是怎样运作的呢?当你只能使用core java,却需要AOP技术时,这个问题的解答变得极为关键.不仅如此,在高级技术岗位的面试中,此类问题也常作为考题出现.这不,我的朋友最近参加了一个面试,就被问到了这样一个棘手的问题--如何在不使用Spring及相关库,只用core Java的条件下实现AOP.因此,我将在

随机推荐