spring基础(3:面向切面编程)

一.面向切面编程

??Spring的基础是IOC和AOP,前面两节对IOC和DI做了简单总结,这里再对AOP进行一个学习总结,Spring基础就算有一个初步了解了。

??在软件开发中,我们可能需要一些跟业务无关但是又必须做的东西,比如日志,事务等,这些分布于应用中多处的功能被称为横切关注点,通常横切关注点从概念上是与应用的业务逻辑相分离的。如何将这些横切关注点与业务逻辑在代码层面进行分离,是面向切面编程(AOP)所要解决的。

? 横切关注点可以被描述为影响应用多处的功能,切面能够帮助我们模块化横切关注点。下图直观呈现了横切关注点的概念:

途中CourseService,StudentService,MiscService都需要类似安全、事务这样的辅助功能,这些辅助功能就被称为横切关注点。

??继承委托是最常见的实现重用通用功能的面向对象技术。但是如果在整个程序中使用相同的基类继承往往会导致一个脆弱的对象体系;而使用委托可能需要对委托对象进行复杂的调用。

? 切面提供了取代继承和委托的另一种选择,而且更加清晰简洁。在面向切面编程时,我们任然在一个地方定义通用功能,但是我们可以通过声明的方式定义这个功能以何种方式在何处应用,而无需修改受影响的类,受影响类完全感受不到切面的存在。

二.AOP常用术语

??下面是AOP中常用的名词。

1. 通知(Advice)

??通知定义了切面是什么以及何时使用。出了描述切面要完成的工作,通知还解决了何时执行这个工作的问题。Sping切面可以应用以下5种类型的通知。

  • Before 在方法被调用之前调用通知
  • After 在方法完成之后调用通知,无论方法执行是否成功
  • After-returning 在方法成功执行后调用通知
  • After-throwing 在方法抛出异常后调用通知
  • Around 通知包裹了被通知的方法,在被通知的方法调用前和调用后执行

2.连接点(Joinpoint)

??应用可能有很多个时机应用通知,这些时机被称为连接点。连接点是应用在执行过程中能够插入切面的一个点,这个点可以是调用方法时、抛出异常时、甚至是修改字段时。切面代码可以利用这些切入到应用的正常流程中,并添加新的行为。

3.切点(Pointcut)

??切点定义了通知所要织入的一个或多个连接点。如果说通知定义了切面的“什么”和“何时”,那么切点就定义了“何处”。通常使用明确的类和方法名称来指定切点,或者利用正则表达式定义匹配的类和方法来指定这些切点。有些AOP框架允许我们创建动态的切点,可以更具运行时的策略来决定是否应用通知。

4.切面(Aspect)

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

5.引入

??引入允许我们想现有的类添加新方法或属性。即在无需修改现有类的情况下让它们具有新的行为和状态。

6.织入

??织入是将切面应用到目标对象来创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中,在目标对象的生命周期里有多个点可以进行织入。

  • 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译期,比如AspectJ的织入编译期
  • 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的加载器,它可以在目标类被引入应用之前增强该目标类的字节码,例如AspectJ5的LTW(load-time weaving)
  • 运行期:切面在应用运行的某个时刻被织入。一般情况下AOP容器会为目标对象动态创建一个代理对象

三.Spring AOP

??Spring在运行期通知对象,通过在代理类中包裹切面,Spring在运行期将切面织入到Spring管理的Bean中。代理类封装了目标类,并拦截被通知的方法的调用,再将调用转发给真正的目标Bean。由于Spring是基于动态代理,所有Spring只支持方法连接点,如果需要方法拦截之外的连接点拦截,我们可以利用Aspect来协助SpringAOP。

??Spring在运行期通知对象,通过在代理类中包裹切面,Spring在运行期将切面织入到Spring管理的Bean中。代理类封装了目标类,并拦截被通知的方法的调用,再将调用转发给真正的目标Bean。由于Spring是基于动态代理,所有Spring只支持方法连接点,如果需要方法拦截之外的连接点拦截,我们可以利用Aspect来协助SpringAOP。

1、定义切点

??在SpringAOP中,需要使用AspectJ的切点表达式语言来定义切点。Spring只支持AspectJ的部分切点指示器,如下表所示:

AspectJ指示器 描述
arg() 限制连接点匹配参数为指定类型的执行方法
@args() 限制连接点匹配参数由指定注解标注的执行方法
execution() 用于匹配是连接点的执行方法
this() 限制连接点匹配AOP代理的Bean引用为指导类型的类
target() 限制连接点匹配目标对象为指定类型的类
@target() 限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型的注解
within() 限制连接点匹配指定的类型
@within() 限制连接点匹配指定注解所标注的类型(当使用SpringAOP时,方法定义在由指定的注解所标注的类里)
@annotation 限制匹配带有指定注解连接点
bean() 使用Bean ID或Bean名称作为参数来限制切点只匹配特定的Bean

?其中只有execution指示器是唯一的执行匹配,其他都是限制匹配。因此execution指示器是

其中只有execution指示器是唯一的执行匹配,其他都是限制匹配。因此execution指示器是我们在编写切点定义时最主要使用的指示器。

2、编写切点

??假设我们要使用execution()指示器选择Hello类的sayHello()方法,表达式如下:

execution(* com.test.Hello.sayHello(..))

方法表达式以*** 号开始,说明不管方法返回值的类型。然后指定全限定类名和方法名。对于方法参数列表,我们使用()标识切点选择任意的sayHello()方法,无论方法入参是什么。

??同时我们可以使用&&(and),||(or),!(not)来连接指示器,如下所示:

execution(* com.test.Hello.sayHello(..)) and !bean(xiaobu)

3、申明切面

??在经典Spring AOP中使用ProxyFactoryBean非常复杂,因此提供了申明式切面的选择,在Spring的AOP配置命名空间中有如下配置元素:

AOP配置元素 描述
<aop:advisor > 定义AOP通知器
<aop:after > 定义AOP后置通知(无论被通知方法是否执行成功)
<aop:after-returning > 定义AOP after-returning通知
<aop:after-throwing > 定义after-throwing
<aop:around > 定义AOP环绕通知
<aop:aspect > 定义切面
<aop:aspectj-autoproxy > 启用@AspectJ注解驱动的切面
<aop:before > 定义AOP前置通知
<aop:config > 顶层的AOP配置元素。大多数的<aop:* >元素必须包含在其中
<aop:declare-parents > 为被通知的对象引入额外的接口,并透明的实现
<aop:pointcut > 定义切点

4、实现

假设有一个演员类Actor,演员类中有一个表演方法perform(),然后还有一个观众类Audience,这两个类都在包com.example.springtest下,Audience类主要方法如下:

public class Audience{
    //搬凳子
    public void takeSeats(){}
    //欢呼
    public void applaud(){}
    //计时,环绕通知需要一个ProceedingJoinPoint参数
    public void timing(ProceedingJoinPoint joinPoint){
        joinPoint.proceed();
    }
    //演砸了
    public void demandRefund(){}
    //测试带参数
    public void dealString(String word){}

}

a、xml配置实现

??首先将Audience配置到springIOC中:

<bean id="audience" class="com.example.springtest.Audience"/>

然后申明通知:

<aop:config>
  <aop:aspect ref="audience">
    <!-- 申明切点 -->
    <aop:pointcut id="performance" expression="execution(* com.example.springtest.Performer.perform(..))"/>
    <!-- 声明传递参数切点 -->
    <aop:pointcut id="performanceStr" expression="execution(* com.example.springtest.Performer.performArg(String) and args(word))"/>
    <!-- 前置通知 -->
    <aop:before pointcut-ref="performance" method="takeSeats"/>
    <!-- 执行成功通知 -->
    <aop:after-returning pointcout-ref="performance" method="applaud"/>
    <!-- 执行异常通知 -->
    <aop:after-throwing pointcut-ref="performance" method="demandRefund"/>
    <!-- 环绕通知 -->
    <aop:around pointcut-ref="performance" method="timing"/>
    <!-- 传递参数 -->
    <aop:before pointcut-ref="performanceStr" arg-names="word" method="dealString"/>
  </aop:aspect>
</aop:config>

b、注解实现

直接在Audience类上加注解(Aspect注解并不能被spring自动发现并注册,要么写到xml中,要么使用@Aspectj注解或者加一个@Component注解),如下所示:

@Aspect
public class Audience{
    //定义切点
    @Pointcut(execution(* com.example.springtest.Performer.perform(..)))
    public void perform(){}

    //定义带参数切点
    @Pointcut(execution(* com.example.springtest.Performer.performArg(String) and args(word)))
    public void performStr(String word){}

    //搬凳子
    @Before("perform()")
    public void takeSeats(){}

    //欢呼
    @AfterReturning("perform()")
    public void applaud(){}

    //计时,环绕通知需要一个ProceedingJoinPoint参数
    @Around("perform()")
    public void timing(ProceedingJoinPoint joinPoint){
        joinPoint.proceed();
    }

    //演砸了
    @AfterThrowing("perform()")
    public void demandRefund(){}

    //带参数
    @Before("performStr(word)")
    public void dealString(String word){}
}

c、通过切面引入新功能

??既然可以用AOP为对象拥有的方法添加新功能,那为什么不能为对象增加新的方法呢?利用被称为引入的AOP概念,切面可以为Spring Bean添加新的方法,示例图如下:

当引入接口的方法被调用时,代理将此调用委托给实现了新接口的某个其他对象。实际上,Bean的实现被拆分到了多个类。

  • xml引入需要使用<aop:declare-parents >元素:

    <aop:aspect>
      <aop:declare-parents types-matching="com.fxb.springtest.Performer+"
        implement-interface="com.fxb.springtest.AddTestInterface"
        default-impl="com.fxb.springtest.AddTestImpl"/>
    </aop:aspect>

    顾名思义&lt;declare-parents>声明了此切面所通知的Bean在它的对象层次结构中有了新的父类型。其中types-matching指定增强的类;implement-interface指定实现新方法的接口;default-imple指定实现了implement-interface接口的实现类,也可以用delegate-ref来指定一个Bean的引用。

  • 注解引入,通过@DeclareParents注解
    @DeclareParents(value="com.fxb.springtest.Performer+",
      defaultImpl=AddTestImpl.class)
    public static AddTestInterface addTestInterface;

    同xml实现一样,注解也由三部分组成:1、value属性相当于tpes-matching属性,标识被增强的类;2、defaultImpl等同于default-imple,指定接口的实现类;3、有@DeclareParents注解所标注的static属性指定了将被引入的接口。

原文地址:https://www.cnblogs.com/wuyoucao/p/9446356.html

时间: 2024-08-26 11:53:43

spring基础(3:面向切面编程)的相关文章

Spring(二)面向切面编程AOP

这篇博客写的比较累赘,好多相同的程序写了好几遍,主要是为了是自己养成这样的一个编程思路,其中应该不乏错误之处,以后好好学,慢慢改吧.------jgp 1 AOP介绍 1.1什么是AOP 面向切面编程(Aspect Oriented Programing):通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP采取横向抽取机制,取代了传统纵向继承体系的重复性代码,主要体现在事务处理.日志管理.权限控制.异常处理等方面,使开发人员在编写业务逻辑时可以专心于核心业务,提高了代码的可

Spring AOP:面向切面编程,AspectJ,是基于spring 的xml文件的方法

导包等不在赘述: 建立一个接口:ArithmeticCalculator,没有实例化的方法: package com.atguigu.spring.aop.impl.panpan; public interface ArithmeticCalculator { //创建一个接口,其是抽象的类,不能实例化 int add(int i,int j); int sub(int i,int j); int mul(int i,int j); int div(int i,int j); } 建立一个类:A

Spring(四):面向切面编程AOP

横切关注点:分布于应用中多处的功能 面向切面编程AOP:将横切关注点与业务逻辑相分离 在使用面向切面编程时,仍在一个地方定义通用功能,但是可以通过声明的方式定义这个功能以何种方式在何处应用,而无需修改受影响的类. 横切关注点可以被模块化为特殊的类,这些类被称为切面. 好处: 每个关注点集中于一处,而不是分散到多处代码中 服务模块更加简洁,因为它们只包含主要关注点的代码,次要关注点被转移到切面中了 1.定义AOP术语 1.1.通知(Advice) 切面的工作被称为通知. 通知定义了切面是什么以及何

Spring的AOP面向切面编程

什么是AOP? 1.AOP概念介绍 所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程. 功能: 让关注点代码与业务代码分离! 关注点: 重复代码就叫做关注点: 业务代码: 核心业务的代码 业务代码与关注点代码分离,好处? --> 关注点代码写一次即可: -->开发者只需要关注核心业务: -->运行时期,执行核心业务代码时候动态植入关注点代码: [代理] 如何分离? 过程式/对象式/代理模式分离 AOP的好处是可以动态地添加和删除在切面上的逻辑而不

spring入门-AOP 面向切面编程

AOP 面向切面编程 在日常开发中最后将业务逻辑定义在一个专门的service包下,而实现定义在service包下的impl包中, 服务接口以IXXXService形式,而服务实现就是XXXService,这就是规约设计 步骤: 1.E:\Users\WorkSpaces\KmwalletApp\spring\aop\test\HelloWorldService.java 继承(implements)xx接口 2.E:\Users\WorkSpaces\KmwalletApp\spring\ao

Spring之AOP(面向切面编程)_入门Demo

软件152 刘安民 AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现. 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行:二是采用静态植入的方式,引入特定的语法创建"方面",从而使得编译器可以在编译期间织入有关"方面"的代

Spring:AOP, 面向切面编程

AOP概述 什么是AOP, 面向切面编程 AOP为Aspect Oriented Programming的缩写, 意为:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP是OOP的延续, 是函数式编程的一种衍生范型. 利用AOP可以对业务逻辑的各个部分进行隔离, 从而使得业务逻辑各部分之间的耦合度降低, 提高程序的可重用性, 同时提高了开发的效率. - 传统开发模型: 纵向的编程.  面向切面编程: 纵横配合的编程. AOP的作用及优势 作用: 在程序运行期

Java面试--Spring技术要点--Spring AOP(面向切面编程)

33  Spring AOP的概念 面向切面的编程,是一种编程技术,是OOP(面向对象编程)的补充和完善.OOP的执行是一种从上往下的流程,并没有从左到右的关系.因此在OOP编程中,会有大量的重复代码.而AOP则是将这些与业务无关的重复代码抽取出来,然后再嵌入到业务代码当中.常见的应用有:权限管理.日志.事务管理等. 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行:二是采用静态织入的方式,引入特定的语法创建"方面"

关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)

本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 如果你正在为你的业务模型使用IoC容器--这是个好主意--你将会想使用某个 Spring.NET's AOP特定的IFactoryObject 的实现(要记住,一个工厂的实例提供了一个间接层,使这个工厂能够创建不同类型的对象-5.3.9节,"通过使用其他类型和实例创建一个对象"). 一个基本的创建Spring.NET

java的动态代理的两种方式和spring的aop面向切面编程的对比

java动态代理的两种方式 使用动态代理的好处:可以进行类的功能的加强,同时减少耦合和代码的冗余,耦合的意思是不用吧加强的部分写到各个实现类里面,冗余的意思是如果对每个实现类加强的部分是一样的,通过一个代理类即可实现 基于jdk的动态代理 通过jdk中自带的Proxy类进行动态的代理,Proxy创建动态代理对象的时候要传入三个参数,第一个是classloader,第二个是interfaces,第三个是代理类实现的方法 要求:代理的是一个接口,必须至少有一个实现类 创建接口的代码: /** * a