第三章 实现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. StackOverflow上面 7个最好的Java答案

    StackOverflow发展到目前,已经成为了全球开发者的金矿.它能够帮助我们找到在各个领域遇到的问题的最有用的解决方案,同时我们也会从中学习到很多新的东西.这篇文章是在我们审阅了StackOver ...

  2. Luat Inside | 多功能YAP物联网终端机,你不会还不知道吧?

    简洁高效是合宙产品的一个重要特点,合宙的工程师们用Demo取代繁杂的说明书,以便于开发者快速上手. 有没有可能把这个学习的过程变得更有趣,并且把技术入门难度进一步降低?作为一名Luat技术爱好者,我对 ...

  3. 如何编写shell脚本

    1.首先创建一个目录 vi hello.sh 2.编写shell第一行 #!/bin/bash    (为了声明是shell脚本,第一行都要这么写) 3.可以添加注释     #the first p ...

  4. Netty 框架学习 —— 单元测试

    EmbeddedChannel 概述 ChannelHandler 是 Netty 程序的关键元素,所以彻底地测试它们应该是你的开发过程中的一个标准部分,EmbeddedChannel 是 Netty ...

  5. Android Studio用上Visual Studio Android Emulator

    背景介绍 第一次接触Android官方的AVD(Android Virtual Device)时你可能会吐槽又慢又丑,不要紧,微软作为新晋安卓阵营最佳开发商,其实也为我们准备了一个脱胎于Windows ...

  6. 正则表达式_爬取豆瓣电影排行Top250

    前言: 利用简单的正则表达式,获取响应内容爬取数据. Part1 正则表达式(Regular Expression) 1.1 简介 正则表达式,又称规则表达式,它是一种文本模式,就是通过事先定义好的一 ...

  7. UI自动化学习笔记- Selenium元素等待(强制等待、显示等待、隐式等待)

    一.元素等待 1. 元素等待 1.1 什么是元素等待 概念:在定位页面元素时如果未找到,会在指定时间内一直等待的过程 意思就是:等待指定元素已被加载出来之后,我们才去定位该元素,就不会出现定位失败的现 ...

  8. Gym - 101128E Wooden Signs DP

    题目大意: 一共n块木板,前两个数给出最底下木块的两个端点,后面n-1个数给出第i层的一个固定端点,问你木块的所有放置情况. 分析: 状态: d[i][j]表示第i个木块,第i-1块木板的未固定端点为 ...

  9. Docker:Linux离线安装docker-compose

    1)首先访问 docker-compose 的 GitHub 版本发布页面 https://github.com/docker/compose/releases 2)由于服务器是 CentOS 系统, ...

  10. 大数据-Hadoop安装

    进入到Hadoop安装包路径下 [atguigu@hadoop101 ~]$ cd /opt/software/ 解压安装文件到/opt/module下面 [atguigu@hadoop101 sof ...