第三章 实现AOP

AOP:面向方面编程,AOP能够使您将所有模块共有的特性与应用程序的主要业务逻辑隔离开

一、AOP介绍

横切关注点:在Web应用程序中,有一些服务(如登录、安全和事务管理)不是应用程序的主要业务逻辑的一部分。但是,这些服务对于Web应用程序是必不可少的,需要在应用程序的每个模块中实现。因此,这些服务被认为是横切关注点,因为它们要横切应用程序的多个模块。

次要问题,因为他们不实现应用程序的核心功能。

1.定义

将代码分解成不同的模块,称为方面,切面支持对关注点进行模块化,比如跨多个类型和对象的事物管理、日志记录和安全性。

AOP的解决方案:不必从方法中调用所有方法,而是在类的方法中定义额外的关注点,比如维护日志等。

2.AOP中的概念与术语

方面:方面是跨多个类的企业应用程序关注点的类。Aspect可以是通过spring XML文件配置的普通类,也可以使用spring AspectJ集成。使用@Aspect将类定义为Aspect

连接点:连接点是应用程序中的一个特定点,比如方法的执行、异常处理等。在spring aop中,连接点总是方法的执行。

通知:通知是针对某个特定的连接点而采取的行动,相当于是在应用程序中到达某个具有匹配切入点的某个连接时候执行的方法。

分类标准:通知的执行方法,spring AOP中有5类通知

前通知:在连接点之前执行的通知,但是不能组织执行流继续到连接点(除非抛出异常)

返回后通知:通知将在连接点正常完成后执行

抛出后通知:如果方法通过抛出异常而退出,则执行通知

后通知:无论连接点以何种方式退出,都要执行通知

围绕通知:围绕连接点的通知,可以在方法调用之前和调用智慧执行自定义行为。它也负责选择是继续到连接点还是通过返回自身的返回值或者抛出一场来简化被建议的方法的执行。

切入点:切入点是与连接点匹配的表达式,以确定是否需要执行通知。(最终应用通知的所选连接点称为切入点)

目标对象Target Object:通知适用的对象。意思是运行时创建一个子类,其中覆盖目标方法,并更具其配置包含通知

AOP代理:Spring AOP实现通过适用JDK动态代理创建带有目标类和通知调用的代理类

织入:它是将方面与其他对象链接以创建已通知代理对象的过程

二、实现AOP

AOP的实现有三个主要的AOP框架提供

spring AOP Aspect J JBoss AOP

三种使用spring AOP的方法

通过使用spring API

使用Aspect J 注释风格

通过spring XML配置样式与spring一起工作

面向方面编程与spring一起工作

spring使用基于代理的机制,它创建了一个代理对象,该代理对象包裹原始对象。并讲接收与方法调用相关的通知。代理对象可以通过代理工厂bean创建,也可以通过XML文件中的自动代理配置创建并在执行完成时销毁。

1.spring Aspect J风格的AOP

通过使用Aspect J 提供的用于切入点解析和匹配的库。AOP运行时候仍然是纯粹的spring AOP,而且不依赖于Aspect J 编译器或者weaver

配置@Aspect J 支持:XML配置或者Java配置

note:两种都要有aspectjweaver.jar库位于应用程序的类路径中。

使用Java类配置启用

添加@EnableAspectJAutoproxy注释

@Configuration

@EnableAspectJAutoProxy

public class AppConfig{



}

spring AspectJ AOP提供了许多注释

@Aspect将类声明为aspect

@Pointcut声明切入点表达式

用于创建通知的注释

@Before 声明前通知 在调用实际方法之前应用它

@After 声明后通知。在调用实际方法之后和返回结果之前应用。

@AfterReturning 声明返回后通知。 在调用实际方法和返回结果之前应用,但是可以在通知中获取结果值。

@Around 声明了围绕通知。 在调用实际方法之前和之后应用

@AfterTrowing 声明了抛出后通知。 如果实际方法抛出应用,则调用该方法。

声明方面

启用@Aspect J 支持后,在应用程序上下文中定义的带有@Aspect J 的方面类的任何bean都会呗spring 自动检测并用于配置Spring AOP。

应用程序上下文中的 一个常规bean定义,指向一个带有@Aspect注释的bean类

声明切入点

spring AOP只执行spring bean的方法执行连接点,将切入点看作匹配spring bean上方法的执行。

切入点声明:签名(由名称和任何参数组成) 切入点表达式(准确确定我们意向的方法执行)

分别由一个常规方法定义提供 和 @Pointcut注释表示

NOTE:作为切入点签名的方法必须有一个void返回类型

Example:

区分切入点签名和切入点表达式

@Pointcut ("excution(*transfer(...))") //the pointcut expression

private void anyOldtransfer(){ } //the pointcut signature

常见切入点的示例

任何公共方法的执行:

excution(public * *(...))

任何以"Xx"开头的方法的执行

excution(* xx*(...))

AccountService接口定义的任何方法的执行

excution(* com.xyz.service.AcountService.*(...))

任何服务包中定义的方法执行

excution(* com.xyz.service.*.*(..))

任何服务包或者子包定义的方法的执行

excution(* com.xyz. service.*. *(..))

服务包中的任何连接点

within(com.xyz.service.*)

声明通知

通知于切入点表达式关联,并在切入点匹配的方法执行之前、之后或者周围运行。切入点表达式可是对命名切入点的简单引用,也可以是在恰当位置声明的切入点表达式

import org.aspectj.lang.annotation.Aspect;

前通知

@Before("com.niit.myapp.SystemArchitecture.dataAccessOperation()")

返回后通知

@AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")

NOTE:返回标记属性中使用的名称必须与通知方法中的参数相对应。return子句害将匹配现状为只匹配哪些返回指定类型值的方法的执行。

抛出后通知

@AfterThrowing("com.niit.myapp.SystemArchitecture.dataAccessOperation()")

使用抛出属性严格匹配,将抛出的异常绑定到一个通知参数

抛出属性中使用的名称必须与通知方法中的参数名称对应。当方法执行抛出异常而退出时,异常将作为相应的参数值传递给通知方法。

后通知

后通知运行时,匹配的方法执行退出。后通知必须住呢比阿红处理正常和异常返回条件,一般用于释放资源。

@After("com.niit.myapp.SystemArchitecture.dataAccessOperation()")

围绕通知

它在方法执行之前和之后执行工作,并确定何时、如何以及是否该方法实际执行。如果需要以线程安全的方式在方法执行之前和之后共享状态,则使用它。

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.ProceedingJoinPoint;

NOTE:最弱方式,即如果前通知可以做,就不要使用围绕通知。

@Around("com.niit.myapp.SystemArchitecture.dataAccessOperation()")

使用XML配置启用@AspectJ支持

<aop:aspectj-autoproxy/>

2.基于spring 模式的AOP(XML配置)

声明方面

使用模式支持,方面只是在spring应用程序上下文中定义为bean的常规Java对象。状态和行为在对象的字段和方法中捕获,切入点和通知信心在XML中捕获。

<aop:config>

<aop:aspect id="myAspect" ref="aBean"> //声明方面。后台Bean,使用ref属性引用

...

</aop:aspect>

</aop:config>

声明切入点

切入点是Spring AOP中的一种表达式语言,表示服务层中任何业务执行的切入点可以定义如下:

<aop:config>

<aop:pointcut id="bussinessService" expression="execution(* com.niit.myapp.service.*.*(..))"/>

</aop:config>

切入点表达式

应用于所有公共方法

<aop:pointcut expression=("execution(public * *(..))")>

应用于所有操作类的公共方法

<aop:pointcut expression=("execution(public Operation. *(..))")>

应用于操作类的所有方法

<aop:pointcut expression=("execution(Operation.*(..))")>

应用于所有员工类的公共setter方法

<aop:pointcut expression="execution(public Employee.set . *(..))")>

应用于所有操作类返回int 值的方法

<aop:pointcut expression="execution(int Operation.*(..))")>

声明通知

前通知

<aop:aspect id="beforeExample" ref="aBean">

<aop:before

pointcut-ref="dataAccessOperation" method="doAccessCheck"/>

</aop:aspect >

返回后通知

<aop:aspect id="afterReturningExample" ref="aBean">

<aop:after-returning

pointcut-ref="dataAccessOperation" method="doAccessCheck"

returning="retval"/>

</aop:aspect >

可以在通知主体中获得返回值,使用返回值标记属性来指定应该传递返回值的参数的名称。

新增一个returning 属性

doAccessCheck方法必须指明一个返回值的参数的名称,签名的方式可以是

public void doAccessCheck(Object reVal){...}

抛出后通知

当匹配的方法执行通过抛出异常结束时执行通知。

<aop:aspect id="afterThrowingExample" ref="aBean">

<aop:after-throwing

pointcut-ref="dataAccessOperation"

throwing ="dataAccessEx"

method="doAccessRecoveryActions"/>

</aop:aspect >

使用抛出标记属性指定异常一个传递到的参数名称

新增一个throwing属性,对应的方法必须声明一个对应的参数(同上)

后通知

在匹配的方法执行退出时执行

<aop:aspect id=afterExample" ref="aBean">

<aop:after

pointcut-ref="dataAccessOperation" method="doRelease"/>

</aop:aspect >

围绕通知

(表述和用注释配置相同)

围绕通知是使用aop:Around元素声明的,通知方法的第一个参数必须是ProceedingJoinPoint类型,在通知的主体中,对ProceedingJoinPoint调用proceed()将执行底层方法。

<aop:aspect id=afterExample" ref="aBean">

<aop:around

pointcut-ref="dataAccessOperation" method="doBasicProfiling"/>

</aop:aspect >

3.使用spring API的AOP

步骤:

创建通知——>定义切入点——>创建代理

创建代理

通知是方面在特定连接点上采取的操作。它是通过创建一个函数,来表示应用程序的辅助逻辑实现的。

一个应用程序可以有一个或者多个通知。

spring API aop中实现4种类型的通知

前通知在实际方法调用之前执行

后通知在实际的方法调用之后执行,如果方法返回值,则在返回值之后执行。

围绕通知在实际方法调用之前和之后执行。

抛出后通知,如果实际方法抛出异常,则执行该方法。

前通知:

它没有中断程序执行的能力,除非抛出异常。

导入org.springfrawork.aop.MethodBeforeAdvice 接口

在接口中定义before方法

public void before{

Method method,Object [] args,Object target

}throws Throwable

method:第一个参数,表示通知用到的方法

args:是对象类型的数组,该数组包含调用方法时传递给方法的参数

target:表示方法调用的目标

返回后:

这个通知再连接带你正常完成后执行

导入org.springframework.aop.AfterReturningAdvice接口

public void afterReturning(Object returnValue, Method method,Object[] arg,

Oject target)throws Throwable

四个参数

returnValue:保存从被调用的方法返回的值

其余三个参数同上

returnValue:保存从被调用的方法返回的值

抛出后

导入org.springframework.aop.ThrowsAdvice接口

public void afterThrowing (Throwable throwbale)

after-throwing()方法接收可抛出类型的一个参数,该参数指示应由通知处理的异常。

创建通知,spring提供的配置元素——

aop:config:定义其中所有AOP的配置,它可以包含定义切入点、通知和方面的元素

aop:aspect:用于声明一个方面,有一个ref标记属性,该属性引用spring配置文件中的定义的相应的方面bean

aop:before:用于定义连接点之前执行的一个方法

aop:after-returning:用于定义连接点之后执行的一个方法

aop:after-throwing:用于定义抛出时异常执行的一个方法

aop:around:用于定义连接点之前和之后执行的一个方法

定义切入点

定义切入点来说明通知要被应用的位置。

切入点的主要目的是选择一个通知应用的地方的方法。切入点在spring配置文件中定义。

要辨别可以应用通知的特定位置或方法,需要指定模式

此模式包含使用正则表达式调用的方法的名称,正则表达式为匹配文本字符串

使用正则表达式定义切入点:

org.springframework.aop.support.JdkRegexpMethodPointcut类

pattern属性,该属性的value标记属性用于指定调用方法的特定模式

使用通配符指定模式,星号*,表示任何类、方法、返回类型或者参数;或者零个或者多个参数的点字符(..)来指定切入点的模式

创建通知器 org.springframework.aop.support.DefaultPonitcutAdvisor,使用其再spring配置文件中定义一个advisor bean

Example:

创建代理

创建一个调用该advisor的地理

代理充当通知、目标对象、连接点、切入点和通知器之间的链接

代理在spring配置文件中作为bean创建,spring提供了org.springframework.aop.config.ProxyFactoryBean类

传递以下参数来创建一个代理

Target:指定您想代理代理的目标对象

interceptorName:代表类型的数组,字符串。指定在spring 配置文件中advisor bean名称列表

proxyInterfaces:代表类型的数组,字符串。指定定义应用程序主要逻辑的接口名称

Example:

mypointCutAdivice

spring第三章的更多相关文章

  1. spring boot 笔记--第三章

    spring boot 笔记 第三章,使用Spring boot 构建系统: 强烈建议支持依赖管理的构建系统,Maven或Gradle 依赖管理: Spring Boot的每版本都会提供它支持的依赖列 ...

  2. 一起来学Spring Cloud | 第三章:服务消费者 (负载均衡Ribbon)

    一.负载均衡的简介: 负载均衡是高可用架构的一个关键组件,主要用来提高性能和可用性,通过负载均衡将流量分发到多个服务器,多服务器能够消除单个服务器的故障,减轻单个服务器的访问压力. 1.服务端负载均衡 ...

  3. Spring 学习指南 第三章 bean的配置 (未完结)

    第三章 bean 的配置 ​ 在本章中,我们将介绍以下内容: bean 定义的继承: 如何解决 bean 类的构造函数的参数: 如何配置原始类型 (如 int .float 等) .集合类型(如 ja ...

  4. 第三章Hibernate关联映射

    第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...

  5. 一起来学Spring Cloud | 第二章:服务注册和发现组件 (Eureka)

    本篇文章,很浅显的一步步讲解如何搭建一个能运行的springcloud项目(带所有操作截图).相信!看完本篇之后,你会觉得springcloud搭建如此简单~~~~ 一. Eureka简介: 1.1  ...

  6. Java Persistence with MyBatis 3(中文版) 第三章 使用XML配置SQL映射器

    关系型数据库和SQL是经受时间考验和验证的数据存储机制.和其他的ORM 框架如Hibernate不同,MyBatis鼓励开发者可以直接使用数据库,而不是将其对开发者隐藏,因为这样可以充分发挥数据库服务 ...

  7. #Spring实战第二章学习笔记————装配Bean

    Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...

  8. 一起来学Spring Cloud | 第一章 :如何搭建一个多模块的springcloud项目

    在spring cloud系列章节中,本来已经写了几个章节了,但是自己看起来有些东西写得比较杂,所以重构了一下springcloud的章节内容,新写了本章节,先教大家在工作中如何搭建一个多模块的spr ...

  9. 《精通Spring4.x企业应用开发实战》第三章

    这一章节主要介绍SpringBoot的使用,也是学习的重点内容,之后就打算用SpringBoot来写后台,所以提前看一下还是很有必要的. 3.SpringBoot概况 3.1.1SpringBoot发 ...

随机推荐

  1. MySQL的自增ID用完了,怎么办?

    既然这块知识点不清楚,那回头就自己动手实践下. 首先,创建一个最简单的表,只包含一个自增id,并插入一条数据. create table t0(id int unsigned auto_increme ...

  2. 性能工具之linux常见日志统计分析命令

    引言 我前几天写过的性能工具之linux三剑客awk.grep.sed详解,我们已经详细介绍 linux 三剑客的基本使用,接下来我们看看具体在性能测试领域的运用,本文主要介绍的是在 Tomcat 和 ...

  3. 在微信小程序中使用阿里图标库Iconfont

    首先想要使用图标,只用上图的五个iconfont相关文件就可以了.(下下来的文件iconfont.wxss开始是.css的后缀,手动改成.wxss就可以在小程序中使用) 然后在app.wxss中引入i ...

  4. http强制缓存、协商缓存、指纹ETag详解

    目录 实操目录及步骤 缓存分类 强制缓存 对比缓存 指纹 Etag 摘要及加密算法 缓存总结 每个浏览器都有一个自己的缓存区,使用缓存区的数据有诸多好处,减少冗余的数据传输,节省网络传输.减少服务器负 ...

  5. excel VBA构造函数就是这么简单

    Function test(a As Integer)'构造函数名字为test参数为a且为int型  If a >= 90 Then     Debug.Print "优秀" ...

  6. linux 查看目录大小

    查看当前目录下各个目录大小容量 du -sh * du -sh /app/* du -h --max-depth=1 .

  7. 40、Linux文件误删除恢复操作

    rm -rf / #此方法删除不了/目录: rm -rf /* #此方法可以删除/目录下的所有内容,禁止使用: 40.1.前言: 作为一个多用户.多任务的操作系统,Linux下的文件一旦被删除,是难以 ...

  8. 低代码Paas开发平台可以本地实施吗

    低代码Paas开发平台可以本地实施吗?答案是肯定的.虽然低代码开发通常是以云端形式面向用户,也就是我们经常看到到aPaaS,而它也更加倾向于SaaS.但实际上,低代码开发平台是可以支持本地部署的,例如 ...

  9. Docker:Docker常用命令

    docker信息 ##查看docker容器版本 docker version ##查看docker容器信息 docker info ##查看docker容器帮助 docker --help 镜像列表 ...

  10. Mybatis学习(5)与spring3集成

    在这一系列文章中,前面讲到纯粹用mybatis 连接数据库,然后 进行增删改查,以及多表联合查询的的例子,但实际项目中,通常会用 spring 这个沾合剂来管理 datasource 等.充分利用sp ...