1)面向切面的Spring 实战笔记

http://blog.51cto.com/turnsole/2072944

1.AOP:面向切面编程

在OOP中模块化的关键单元是类(classes),而在AOP中模块化的单元则是切面。

AOP框架是Spring的一个重要组成部分。但是Spring IoC容器并不依赖于AOP,这意味着你有权利选择是否使用AOP,AOP做为Spring IoC容器的一个补充,使它成为一个强大的中间件解决方案。

AOP在Spring Framework中的作用

提供声明式企业服务,特别是为了替代EJB声明式服务。最重要的服务是声明性事务管理。

允许用户实现自定义切面,用AOP来完善OOP的使用。

    横切关注点:散布于应用中多处的功能。横切关注点可以被模块化为特殊的类,这些类被称为切面(aspect)。

    AOP可以实现横切关注点与它们所影响的对象之间的解耦。

2.AOP定义

 通知(Advice):

        切面的工作被称为通知。通知定义了切面是什么及何时使用。

        许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。

        Spring切面可以应用5种类型的通知:

--前置通知(Before):在目标方法被调用之前调用通知功能;

--后置通知(After):在目标方法被调用之后调用通知,此时不会关系方法的输出是什么(不论是正常返回还是异常退出);

-- 返回通知(After-returning):在目标方法成功执行之后调用通知;

            -- 异常通知(After-throwing):在目标方法抛出异常后调用通知;

-- 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义行为。包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。

 连接点(Join Point):

        在应用执行过程中能够插入切面的一个点。可以是调用方法时、抛出异常时、修改字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

 切点(Point):

        定义了何处。切点的定义会匹配通知所要织入的一个或多个连接点。通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名来指定这些切点。有些AOP框架允许我们创建动态的切点,可以根据运行时的决策(如方法的参数值)来决定是否应由通知。

切点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切点语法。

 切面(Aspect):

        切面是通知和切点的结合。通知和切点共同定义了切面的全部内容:是什么,在何时何处完成其功能。

 引入(Introduction):

允许我们向现有的类添加新方法或属性。从而可以在无需修改这些现有的类的情况下,让他们具有新的行为和状态。例如,你可以使用引入来使一个bean实现IsModified接口,以便简化缓存机制。

 织入(Weaving):

        把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。

        在目标对象的生命周期里有多个点可以进行织入:

            -- 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入到切面的。

            -- 类加载期:切面在目标类加载到JVM时被织入。需要特殊类加载器,可以在目标类被引入应用之前增强该目标类的字节码。

            -- 运行期:切面在运行的某个时刻被织入。一般情况下,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是以这种方式织入切面的。

综上,通知包含了需要用于多个应用对象的横切行为;

               连接点世程序执行过程中能够应用通知的所有点;

               切点定义了通知被应用的具体位置(在哪些连接点);

     其中关键的概念是切点定义了哪些连接点会得到通知。    


3.Spring对AOP的支持

     创建切点来定义切面所织入的连接点是AOP框架的基本功能。

     Spring提供了4种类型的AOP支持:

          -- 基于代理的经典Spring AOP;

          -- 纯POJO切面;

          -- @AspectJ注解驱动的切面;

          -- 注入式AspectJ切面(适用于Spring各版本);

     前三种都是Spring AOP实现的变体,Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。

     Spring在运行时通知对象:在代理累中包裹切面,Spring在运行期把切面织入到Spring管理的bean中,如下图,代理类封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。当代理拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑。

     直到应用需要被代理的bean时,Spring才创建代理对象。

     Spring只支持方法级别的连接点,如果需要方法拦截之外的连接点拦截之外的连接点拦截功能,可以利用Aspect来补充Spring AOP功能。

3.通过切点来选择连接点

     Spring AOP使用AspectJ的切点表达式语言来定义切点。

     Spring AOP所支持的AspectJ切点指示器:

AspectJ指示器描述

arg()限制连接点匹配参数为指定类型的执行方法

@args()限制连接点匹配参数由指定注解注标的执行方法

execution()用于匹配时连接点的执行方法

this()限制连接点匹配AOP代理的bean引用为指定类型的类

target限制连接点匹配目标对象为指定类型的类

@target()限制连接点匹配特定的执行对象,这些对象对应的类要具有指定类型的注解

within()限制连接点匹配指定的类型

@within()限制连接点匹配指定注解所标注的类型(当使用Spring AOP时,方法定义在由指定的注解所标注的类型)

@annotation限定匹配带有指定注解的连接点

    Spring AOP配置元素以非侵入性方式声明切面:

AOP配置元素用途

定义AOP通知器

定义AOP后置通知(不管被通知的方法是否执行成功)

定义AOP返回通知

定义AOP异常通知

定义AOP环绕通知

定义一个切面

启用@AspectJ注解驱动的切面

定义一个AOP前置通知

顶层的AOP配置元素,大多数的元素必须包含在元素内

以透明的方式为被通知的对象引入额外的接口

定义一个切点

     在XML中使用元素声明环绕通知:

1

2

3

4

5

6

7

8

9

10

          --引用audience Bean


               id="performance"

               expression="execution(* concert.Performance.perform(..))"/>


               pointcut-ref="performance"

               method="watchPerformance"/>


     配置参数化的切面:

1

2

3

4

5

6

7

8

9

10

          --将TrackCounter声明为切面


               id="performance"

               expression="execution(* soundsystem.CompactDisc.playTrack(int)) && args(trackNumber)"/>


               pointcut-ref="trackPlayed"

               method="countTrack"/>


     通过切面引入新功能:

1

2

3

4

5

6

7


          types-matching="concert.Performance+"

          implement-interface="concert.Encoreable"

          delegate-ref="encoreableDelegate"

     />


delegate-ref属性引用了一个Spring bean作为引入委托。这需要在Spring上下文中存在一个ID为encoreableDelegate的bean。

4.注入AspectJ切面

     如果在执行通知时切面依赖于一个或多个类,我们可以在切面内部实例化这些协作的对象。但更好的方式是,我们可以借助Spring的依赖注入把bean装配进AspectJ切面中。

     AspectJ切面不需要Spring就可以织入到应用中。想使用Spring的依赖注入为AspectJ切面注入协作者,就需要在Spring配置中把切面声明为一个Spring配置中的。如下的声明会把criticismEngine bean注入到CriticAspect中:

1

2

3

4

     factory-method="aspectOf">  --获取引用

     Aspect切面是由AspectJ在运行期创建的。所有的AspectJ切面都提供了一个静态的aspectOf()方法,该方法返回切面的一个单例。所以为了获得切面的实例,必须使用factory-method来调用aspectOf()方法而不是调用CriticAspect的构造方法。

     Spring不能像之前那样使用声明来创建一个CriticAspect实例--它已经在运行时由AspectJ创建完成了。Spring需要通过aspectOf()工厂方法获得切面的引用,然后像元素规定的那样在该对象上执行依赖注入。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容