Spring实战笔记:Spring核心(二)

spring core

面向切面的Spring

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:advisor> 定义AOP通知器
<aop:after> 定义AOP后置通知(不管被通知的方法是否执行成功)
<aop:after-returning> 定义AOP返回通知
<aop:after-throwing> 定义AOP异常通知
<aop:around> 定义AOP环绕通知
<aop:aspect> 定义一个切面
<aop:aspectj-autoproxy> 启用@AspectJ注解驱动的切面
<aop:before> 定义一个AOP前置通知
<aop:config> 顶层的AOP配置元素,大多数的<aop:*>元素必须包含在<aop:config>元素内
<aop:declare-parents> 以透明的方式为被通知的对象引入额外的接口
<aop:pointcut> 定义一个切点

在XML中使用<aop:around>元素声明环绕通知:

<aop:config>
     <aop:aspect ref="audience">     --引用audience Bean
          <aop:pointcut              --定义切点 
               id="performance"
               expression="execution(* concert.Performance.perform(..))" />
          <aop:around                --声明环绕通知,引用切点 
               pointcut-ref="performance"
               method="watchPerformance" />
     </aop:aspect>
</aop:config>

配置参数化的切面:

<aop:config>
     <aop:aspect ref="trackCounter">     --将TrackCounter声明为切面
          <aop:pointcut              --定义切点 
               id="performance"
               expression="execution(* soundsystem.CompactDisc.playTrack(int)) && args(trackNumber)" />
          <aop:before                --声明前置通知,引用切点 
               pointcut-ref="trackPlayed"
               method="countTrack" />
     </aop:aspect>
</aop:config>

通过切面引入新功能:

<aop:aspect>
     <aop:declare-parents
          types-matching="concert.Performance+"
          implement-interface="concert.Encoreable"
          delegate-ref="encoreableDelegate"
     />
 </aop:aspect>

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

4.注入AspectJ切面

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

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

<bean class="com.springinaction.springidol.CriticAspect"
     factory-method="aspectOf">  --获取引用
<property name="criticismEngine" ref="criticismEngine"/>
</bean>

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

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

原文地址:http://blog.51cto.com/turnsole/2072944

时间: 2024-11-03 01:28:27

Spring实战笔记:Spring核心(二)的相关文章

Spring实战笔记2---Bean的装配

创建应用对象之间协作关系的行为通常成为装配,该篇的主要内容有两个,一个Spring装配Bean的几种方式以及Spring表达式,其实这两者是分不开的,在Spring中,对象无需自己负责查找或者创建与其关联的其他对象,相反容器负责把需要相互协作的对象一引用赋予各个对象,目前我们先说声明式的装配,注解式的装配等溜到下篇再详细记录,在声明用的xml配置文件中,可以使用表达式来完成一些简单的逻辑处理,和方法调用或者对象引用,在有些特殊的需求当中非它莫属,首先是装配Bean 声明Bean <bean id

(转) Spring读书笔记-----Spring的Bean之配置依赖

前一篇博客介绍了Spring中的Bean的基本概念和作用域(Spring读书笔记-----Spring的Bean之Bean的基本概念),现在介绍Spring Bean的基本配置. 从开始我们知道Java应用中各组件的相互调用的实质可以归纳为依赖关系.根据注入方式的不同,Bean的依赖注入可以分为两种形式: 1.  属性:通过<property …/>元素配置,对应设置注入. 2.  构造器参数:通过<constructor-arg…/>元素配置,对应构造注入. 不管是属性,还是构造

(转)Spring读书笔记-----Spring核心机制:依赖注入

Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的.因此,我们说这些对象间存在依赖关系.加入A组件调用了B组件的方法,我们就可以称A组件依赖于B组件.我们通过使用依赖注入,Java EE应用中的各种组件不需要以硬编码方式耦合在一起,甚至无需使用工厂模式.当某个Java 实例需要其他Java 实例时,系统自动提供所需要的实例,无需程序显示获取,这种自动提供java实例我们谓之为依赖注入,也可以称之为控制反转(Inversi

(一)《Spring实战》——Spring核心

<Spring实战>(第4版) 第一章:Spring之旅 1. 简化Java开发 为了降低Java开发的复杂性,Spring采取了以下4种关键策略: 基于POJO的轻量级和最小侵入性编程: 通过依赖注入和面向接口实现松耦合: 基于切面和惯例进行声明式编程: 通过切面和模板减少样板式代码. 1.1 激发POJO的潜能 在基于Spring构建的应用中,它的类通常没有任何痕迹表明你使用了Spring.最坏的场景是,一个类或许会使用Spring注解,但它依旧是POJO. Spring赋予POJO魔力的

Spring学习笔记--Spring IOC

沿着我们上一篇的学习笔记,我们继续通过代码学习IOC这一设计思想. 6.Hello类 第一步:首先创建一个类Hello package cn.sxt.bean; public class Hello { private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("hello,"+name); } } 第二步:创建配置

Spring学习笔记--Spring简介

1.spring:给软件行业带来了春天; 2.spring的理念:spring框架的初衷是使的现有的更加实用,spring不是创造轮子(技术或框架),而是使现有的轮子更好的运转;spring本身是一个大杂烩,整合现有的框架技术: 3.Spring优点: 轻量级框架:不具备侵入性(使用某个框架,我们不需要实现它的某个接口,方便框架的替换,原有的代码不需要替换); Ioc容器:控制反转; Aop:面向切面编程; 对事务的支持: 对矿建的支持; ................... 4.主要内容:

Spring实战-Spring in Action, 4th Edition-2015年第4版本

In Action系列中最畅销的Spring图书,近十万读者学习Spring的共同选择!In Action系列中最畅销的Spring图书,有近10万读者选择本书来学习Spring! Spring框架已经成为Java开发人员的必备知识,而且Spring 3引入了强大的新特性,例如SpEL.Spring表达式语言.IoC容器的新注解以及用户急需的对REST的支持.无论你是刚刚接触Spring还是被Spring 3.0的新特性所吸引,本书都是掌握Spring的最佳选择. 下载地址: Spring in

Spring实战笔记二

一.Spring配置的方式 spring容器用来创建应用程序中的bean,并通过DI来协调这些对象间的关系. 在bean进行装配时,spring提供了三种主要的装配机制. ①在XML中进行显式配置 ②在Java中进行显式配置 ③隐式的bean发现机制和自动装配 二.自动化装配bean 1.spring从两个角度来实现自动化装配 ①组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean ②自动装配(autowiring):Spring自动满足bean之

(二)《Spring实战》——Spring核心

第二章:装配Bean 在Spring中,对象无需自己查找或创建与其所关联的其他对象.相反,容器负责把需要相互协作的对象引用赋予各个对象.例如,一个订单管理组件需要信用卡认证组件,但它不需要自己创建信用卡认证组件.订单管理组件只需要表明自己两手空空,容器就会主动赋予它一个信用卡认证组件. 创建应用对象之间协作关系的行为通常称为装配(wiring),这也是依赖注入(DI)的本质. 1. Spring配置的可选方案 Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系.但是,