Spring框架:AOP详解

AOP的中文名称叫做面向切面编程。这个名字非常形象,因为你真的可以把一个系统像面包一样切开,并直接在面包上增加修饰。切面可大可小,大到整个系统,小到某一个方法。

AOP有什么用呢?举个例子,每个组件中都可能含有安全、事务、数据库等方面的逻辑,AOP就是把每个组件中的安全作为一个方面进行集中处理,事务作为一个方面,数据库作为一个方面等等。这样才能做到高内聚、低耦合。AOP中有三个重要的术语:通知、切点、连接点。他们之间的关系如下图。

AOP实现的原理是修改目标类中的代码。至于怎么修改,有多种方式:编译时、类加载时、运行时。编译时修改需要特殊的编译器,类加载时修改需要特殊的类加载器。运行时,就是应用在运行的时候AOP框架会为目标对象生成一个动态代理类。Spring AOP采用的就是运行时代理。Spring容器通过ObjectFactory创建所有的Bean实例,并且实例之外增加一层动态代理。SpringAOP具体实现主要涉及到反射机制中的Proxy.newProxyInstance和InvocationHandler,在后续的JVM文章中还会详细介绍。

除了Spring AOP目前流行的AOP框架还有AspectJ、JBoss AOP。

下面是AOP的Hello World程序。目标是,在某个类的createApple方法调用之前做一些事情,但是又不能直接改变这个方法的代码。下面这段代码就是在createApple方法执行之前,额外执行beforeCreateApple,有点类似于Hook。代码如下:

<bean id="appleListener" class="xxx"/>

<aop:aspect ref="appleListener">
  <aop:pointcut id="apple" expression="execution(* *.createApple(..))" />

  <aop:before pointcut-ref="apple" method="beforeCreateApple" />
</aop:aspect>

上面这段代码的意思是,当程序中任何一个类的createApple方法被调用之前,都先调用appleListener中的beforeCreateApple方法。

切点表达式语言。上面例子中的execution(* *.createApple(..))就是表达式语言,第一个星号表示返回值的类型,第二个星号表示被调用的类名。支持如下语法:

  • args() 将参数传递给切面
  • @args() 匹配注解才传递参数
  • execution() 匹配具体的方法
  • this() 匹配当前bean
  • target() 匹配目标对象
  • @target() 匹配目标对象的注解
  • within() 匹配实例的类型
  • @within() 匹配实例的注解
  • @annotation() 匹配注解
  • bean() 匹配bean id

下面举例说明切点表达式语言。

// 切点为执行com.example.Apple.eat方法,返回值任意,参数任意。
execution(* com.example.Apple.eat(..))

// within表示只匹配com.example.*下的任意方法。用了and连接符号。
execution(* com.example.Apple.eat(..) and within(com.example.*))

// bean表示匹配相应的bean
execution(* com.example.Apple.eat(..) and bean(apple))

下面的例子演示了切点的各种修饰方式。

<aop:config>
  <!--定义切面,test是事先定义好的一个bean-->
  <aop:aspect ref="test">
    <!--定义切点-->
    <aop:pointcup id="apple-eat" expression="execution(* com.example.Apple.eat(..))"/>

    <!--在切点之前调用test.beforeEat-->
    <aop:before pointcut-ref="apple-eat" method="beforeEat"/>

    <!--在切点执行成功之后调用-->
    <aop:after-return pointcut-ref="apple-eat" method="eatSuccess"/>

    <!--在切点执行失败之后调用-->
    <aop:after-throwing pointcut-ref="apple-eat" method="eatFailed"/>

    <!--在切点之后调用,不管成功失败-->
    <aop:after pointcut-ref="apple-eat" method="afterEat"/>

    <!--环绕通知,下面有详细说明-->
    <aop:around pointcut-ref="apple-eat" method="eatApple"/>

    <!--动态增加接口,下面有详细说明-->
    <aop:declare-parents types-matching="com.example.Apple+" implement-interface="com.example.Fruit" default-impl="com.example.FruitImpl"/>
  </aop:aspect>
</aop:config>

现代化的Spring支持注解方式的切面。下面请看例子。

// 定义切面
@Aspect
public class Test {
    // 定义切点。方法中不需要写任何代码。
    @Pointcut("execution(* com.example.Apple.eat(..))")
    public void appleEat() { }

    // 切面之前
    @Before("appleEat()")
    public void beforeEat() { }

    // 切面执行成功之后
    @AfterReturning("appleEat()")
    public void eatSuccess() { }

    // 切面执行失败之后
    @AfterThrowing("appleEat()")
    public void eatFailed() { }

    // 切面之后,不管成功失败
    @After("appleEat()")
    public void afterEat() { }

    // 环绕切面,下面有详细说明
    @Around("appleEat")
    public void eatApple(ProceedingJoinPoint joinpoint) { }

    // 定义传递参数的切点
    @Pointcut("execution(* com.example.Apple.eat(..)) and args(size)")
    public void appleEat2() { }

    // 接收切点的参数
    @Before("appleEat2")
    public void beforeEat2(int size) {
        // 能够得到切点的size参数
    }
}

环绕通知。它的目的是为了解决切点前后无法通信的问题。本质是四种切点的结合体。比如我想记录一个切点的执行时间,就需要用到环绕通知。下面是环绕通知的代码。

public void eatApple(ProceedingJoinPoint joinPoint) {
    // 在切点之前
    System.out.println("before pointcut");

    // 手动执行切点
    joinPoint.proceed();

    // 在切点之后
    System.out.println("after pointcut");
}

Introduction引入,也就是动态增加新接口。它的作用就是在程序运行的过程中动态地为一个实例增加接口。请看下面的例子。

// Introduction引入。
@DeclareParents(value="com.example.Phone+", defaultImpl="com.example.AppleWatchImpl")
public static AppleWatch appleWatch;

上面的例子中给appleWatch字段增加了一个注解,意思是让appleWatch字段可以转换成Phone类型,原本appleWatch是不能转换成Phone的。

时间: 2024-11-03 22:22:19

Spring框架:AOP详解的相关文章

Spring框架Aop详解

一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnblogs.com/xrq730/p/4919025.html AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入封装.继承.多态等概念来建立一种对象层次

Spring的AOP详解

Spring的AOP详解 一.AOP基础 1.1AOP是什么 考虑这样一个问题:需要对系统中的某些业务做日志记录,比如支付系统中的支付业务需要记录支付相关日志,对于支付系统可能相当复杂,比如可能有自己的支付系统,也可能引入第三方支付平台,面对这样的支付系统该如何解决呢? 传统解决方案 1.日志部分定义公共类LogUtils,定义logPayBegin方法用于记录支付开始日志, logPayEnd用于记录支付结果 logPayBegin(long userId,long money) logPay

(三)Spring 之AOP 详解

第一节:AOP 简介 AOP 简介:百度百科: 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个重要内容.利用AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等. -------- 这里我先开头讲一个例子代码程序: T.java: 1 package c

spring之aop详解

面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 原文地址:https://www.cnblogs.com/nidegui/p/11069477.html

Spring Framework AOP详解

此前对于AOP的使用仅限于声明式事务,除此之外在实际开发中也没有遇到过与之相关的问题.最近项目中遇到了以下几点需求,仔细思考之后,觉得采用AOP来解决.一方面是为了以更加灵活的方式来解决问题,另一方面是借此机会深入学习SpringAOP相关的内容.本文是权当本人的自己AOP学习笔记,以下需求不用AOP肯定也能解决,至于是否牵强附会,仁者见仁智者见智. 对部分函数的调用进行日志记录,用于观察特定问题在运行过程中的函数调用情况 监控部分重要函数,若抛出指定的异常,需要以短信或邮件方式通知相关人员 金

3、Spring的AOP详解和案例

AOP(Aspect Oriented Programming),即面向切面编程. 1.OOP回顾 在介绍AOP之前先来回顾一下大家都比较熟悉的OOP(Object Oriented Programming).OOP主要是为了实现编程的重用性.灵活性和扩展性.它的几个特征分别是继承.封装.多态和抽象.OOP重点体现在编程架构,强调的是类之间的层次关系. 2.OOP缺陷 为了更好的说明OOP的概念,我们接下来讲一个OOP的实例,重点分析OOP存在哪些缺陷,以便更好的理解AOP的相关内容. 先看如下

spring框架 AOP核心详解

AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知 (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用 (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

S2SH框架集成详解(Struts 2.3.16 + Spring 3.2.6 + Hibernate 3.6.10)

近期集成了一次较新版本的s2sh,出现了不少问题,网上资料也是良莠不齐,有的甚至就是扯淡,简单的把jar包扔进去就以为是集成成功了,在这里整理一下详细的步骤,若哪位有什么不同看法,可以留言,欢迎批评改正. 首先说下集成的环境,Eclipse 4.4,Tomcat 7.0.54,Struts2.3.16,Hibernate3.6.10,Spring3.2.6 相关JAR包已上传至百度云:http://pan.baidu.com/s/1pJluA5l 搭建Struts2框架 1. 创建Java We

Spring AOP详解(转载)

此前对于AOP的使用仅限于声明式事务,除此之外在实际开发中也没有遇到过与之相关的问题.最近项目中遇到了以下几点需求,仔细思考之后,觉得采用AOP 来解决.一方面是为了以更加灵活的方式来解决问题,另一方面是借此机会深入学习Spring AOP相关的内容.本文是权当本人的自己AOP学习笔记,以下需求不用AOP肯定也能解决,至于是否牵强附会,仁者见仁智者见智. 对部分函数的调用进行日志记录,用于观察特定问题在运行过程中的函数调用情况 监控部分重要函数,若抛出指定的异常,需要以短信或邮件方式通知相关人员

Spring AOP详解(转载)所需要的包

上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑,没有main方法,是怎么运行的.这是用的junit,结合spring来进行的测试类. Spring AOP详解(转载)所需要的包,布布扣,bubuko.com