全部章节   >>>>


本章目录

3.1 AOP基本概念和术语

3.1.1 AOP概念

3.1.2 AOP的术语解释

3.1.3 通知类型介绍

3.1.4 通过AOP模拟事务操作

3.1.5 实践练习

3.2  基于XML配置的AOP开发

3.2.1  使用标签定义切入点

3.2.1  使用标签定义切入点

3.2.2 使用标签来前置增强

3.2.3 使用标签来后置增强

3.2.4 使用标签处理异常

3.2.5 实践练习

3.3 基于注解的AOP开发

3.3.1 使用@Pointcut和@Around完成环绕增强

3.3.2 使用@After完成最终增强

3.3.3 使用@Before完成前置增强

3.3.4 使用@AfterReturning完成后置增强

3.3.5 使用@AfterThrowing异常拦截

3.3.6 实践练习

3.4 综合案例

3.4.1 需求说明

3.4.2 实现思路

3.4.3 实践练习

总结


3.1 AOP基本概念和术语

3.1.1 AOP概念

面向切面编程(Aspect Oriented Programming,AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP是面向对象编程(Object Oriented Programming,OOP)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。

利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。常用于日志记录、性能统计、安全控制、事务处理以及异常处理等等。

3.1.2 AOP的术语解释

AOP的关键术语:

切面(Aspect):是共有功能的实现。

连接点(Join Point):是程序在运行过程中能够插入切面的地点。

通知(Advice):即增强,是切面的具体实现。分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、环绕通知(Around)和最终通知(After)

切入点(Pointcut):用于定义通知应该切入到哪些连接点上。

目标对象(Target):是即将切入切面的对象,即那些被通知的对象。

代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。

织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。

3.1.3 通知类型介绍

AOP为通知定义了org.asoalliance.Advice接口,Spring支持5种类型的通知:

前置通知:表示在连接点被调用前执行的通知。

后置通知:表示在某个连接点成功执行之后执行的通知。

环绕通知:表示包围一个连接点通知,在被通知的方法调用之前和之后执行自定义的方法

异常通知:表示在方法抛出异常后执行的通知。

最终通知:表示在某个连接点执行之后执行的通知。

3.1.4 通过AOP模拟事务操作

使用AOP中的环绕通知来模拟事务操作

引入相关jar包

引入aop约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
<!—此处输入内容-->
</beans>

在com.mhys.demo.service包下创建OrderService类,声明insertOrder()方法

在com.mhys.demo.advice包下创建TransactionAdvice类,声明around()方法和after()方法

在applicationContext.xml配置文件中配置目标对象、通知对象和切入点

	<!-- 配置目标对象 -->
<bean id="orderService" class="com.mhys.demo.service.OrderService"></bean>
<!-- 配置通知对象 -->
<bean id="transactionAdvice" class="com.mhys.demo.advice.TransactionAdvice"></bean>
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.mhys.demo.service.*Service.*(..))" id="pointCut"/>
<aop:aspect ref="transactionAdvice">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointCut"/>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>

在com.mhys.demo.test包下编写测试类

3.1.5 实践练习

3.2  基于XML配置的AOP开发

3.2.1  使用<aop:pointcut />标签定义切入点

切入点是指哪些方法需要被执行“AOP”,是由“Pointcut Expression”来描述的。

Expression常用方法有方法参数匹配、方法描述匹配、目标类匹配等,其中最常用的是方法描述匹配。

语法:

execution(<修饰符模式>?<返回类型模式><声明类型模式>?<方法名模式>(<参数模式>)<异常模式>?)

3.2.1  使用<aop:pointcut />标签定义切入点

6种使用execution()表达式实例。:

execution(public void com.mhys.demo.UserServiceImpl.save())

execution(void com.mhys.demo.UserServiceImpl.save())表达式

execution(* com.mhys.demo.UserServiceImpl.save())表达式

execution(* com.mhys.demo.UserServiceImpl.*())表达式

execution(* com.mhys.demo.*ServiceImpl.*(..))表达式

execution(* com.mhys.demo..*ServiceImpl.*(..))表达式

示例:定义一个切入点配置某个包以及子包下的以Service结尾的类中任意返回值、任意参数的以add开头的所有方法,然后在织入最终通知

<!-- 配置目标对象 -->
<bean id="userService" class="com.mhys.demo.user.UserService"></bean>
<bean id="orderService" class="com.mhys.demo.order.OrderService"></bean>
<!-- 配置通知对象 -->
<bean id="myAdvice" class="com.mhys.demo.advice.MyAdvice"></bean>
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.mhys.demo..*Service.add*(..))" id="pointCut"/>
<aop:aspect ref="myAdvice">
<!—最终通知 -->
<aop:after method="afterAdvice" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>

3.2.2 使用<aop:before />标签来前置增强

前置通知是在目标方法之前执行。常见的应用场景是使用前置通知可以在目标方法执行之前执行,插入系统日志。

语法:

<aop:before method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>

示例:在MyAdvice通知类中,声明一个beforeAdvice()前置增强方法,然后在applicationContext.xml配置文件中使用<aop:before />标签织入前置通知

	<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.mhys.demo..*Service.add*(..))" id="pointCut"/>
<aop:aspect ref="myAdvice">
<!-- 最终通知 -->
<aop:after method="afterAdvice" pointcut-ref="pointCut"/>
<!-- 前置通知 -->
<aop:before method="beforeAdvice" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>

3.2.3 使用<aop:after-returning />标签来后置增强

后置通知是在目标方法执行成功之后执行。其使用方法和前置通知类似。通过后置通知可以为目标方法添加新的逻辑代码,使业务方法增强。

语法:

<aop:after-runturning method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>

示例:在MyAdvice通知类中,声明一个afterReturningAdvice()后置增强方法,然后在applicationContext.xml配置文件中使用<aop:after-returning />标签织入后置通知。

	<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.mhys.demo..*Service.add*(..))" id="pointCut"/>
<aop:aspect ref="myAdvice">
<!-- 最终通知 -->
<aop:after method="afterAdvice" pointcut-ref="pointCut"/>
<!-- 前置通知 -->
<aop:before method="beforeAdvice" pointcut-ref="pointCut"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturningAdvice" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>

3.2.4 使用<aop:after-throwing />标签处理异常

异常通知是在方法抛出异常后执行的通知,它最适合的应用场景是在事务管理中。当参与事务的某个Dao发生异常时,事务管理器就必须回滚事务。

语法:

<aop:after-throwing method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>

示例:

在MyAdvice通知类中,声明一个afterthrowingAdvice()异常增强方法;然后在applicationContext.xml配置文件中使用<aop:after-throwing />标签织入异常通知。

<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.mhys.demo..*Service.add*(..))" id="pointCut"/>
<aop:aspect ref="myAdvice">
<!-- 最终通知 -->
<aop:after method="afterAdvice" pointcut-ref="pointCut"/>
<!-- 前置通知 -->
<aop:before method="beforeAdvice" pointcut-ref="pointCut"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturningAdvice" pointcut-ref="pointCut"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowingAdvice" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>

3.2.5 实践练习

3.3 基于注解的AOP开发

3.3.1 使用@Pointcut和@Around完成环绕增强

示例:使用@Pointcut定义切入点,@Round定义环绕增强方法。模拟实现事务的开启和提交操作。

	<!-- 开启注解扫描 -->
<context:component-scan base-package="com.mhys.demo"></context:component-scan>
<!-- 启动AOP注解 -->
<aop:aspectj-autoproxy ></aop:aspectj-autoproxy>

3.3.2 使用@After完成最终增强

示例:在TransactionAdvice通知类中声明一个afterAdvice()最终通知方法,然后使用@After定义最终通知。

@Component
@Aspect
// 表示该类是一个通知类
public class TransactionAdvice {
// 原有代码省略
@After("TransactionAdvice.pc()")
public void afterAdvice(){
System.out.println("关闭事务");
}
}

新增afterAdvice()最终增强方法

3.3.3 使用@Before完成前置增强

示例:在TransactionAdvice通知类中声明一个beforeAdvice()前置增强方法,然后使用@Before定义前置通知。

@Component
@Aspect
// 表示该类是一个通知类
public class TransactionAdvice {
// 代码省略
@Before("TransactionAdvice.pc()")
public void beforeAdvice(){
System.out.println("执行前置通知方法!");
}
}

新增beforeAdvice()前置增强方法

3.3.4 使用@AfterReturning完成后置增强

示例:在TransactionAdvice通知类中声明一个afterReturningAdvice()后置增强方法,然后使用@AfterReturning定义后置通知。

@Component
@Aspect
// 表示该类是一个通知类
public class TransactionAdvice {
// 代码省略
@AfterReturning("TransactionAdvice.pc()")
public void afterReturningAdvice(){
System.out.println("执行后置通知方法!");
}
}

新增afterReturningAdvice()后置增强方法

3.3.5 使用@AfterThrowing异常拦截

示例:在TransactionAdvice通知类中声明一个afterThrowingAdvice()异常增强方法,然后使用@AfterThrowingg定义异常通知。

@Component
@Aspect
// 表示该类是一个通知类
public class TransactionAdvice {
// 代码省略
@AfterThrowing("TransactionAdvice.pc()")
public void afterThrowingAdvice(){
System.out.println("发现异常,执行异常通知方法!");
}
}

新增afterThrowingAdvice异常增强方法

3.3.6 实践练习

3.4 综合案例

3.4.1 需求说明

对于CRM的系统而言,现在有很多的Dao类,比如客户的Dao,联系人的Dao等等。

客户提出一个需求,需要开发人员实现一个功能,对所有的Dao的类中的以get、find开头的方法实现日志输出打印,检测方法的性能,对所有的Dao类中的以save、add、insert、modify、update、delete以及del开头的方法实现事务的开启、提交和关闭操作。要求如下:

  • 使用前置通知和后置通知实现日志输出打印。
  • 使用环绕通知实现事务的开启和提交操作。
  • 使用最终通知实现事务的关闭操作。

3.4.2 实现思路

需求说明解决思路:

在applicationContext.ml配置文件中开启注解扫描功能和AOP注解功能。

在com.mhys.demo.dao包下创建CustomerDao接口,声明getCustomerAll()方法、addCustomer()方法、modifyCustomer()方法和deleteCustomer()方法。 在com.mhys.demo.dao包下创建CustomerDaoImpl类,实现CustomerDao接口,实现接口4个方法。

在com.mhys.demo.dao包下创建LinkmanDao接口,声明getLinkmanAll()方法、addLinkman()方法、modifyLinkman()方法和deleteLinkman()方法。

在com.mhys.demo.dao包下创建LinkmanDaoImpl类,实现LinkmanDao接口,实现接口4个方法。

在com.mhys.demo.service包下创建CustomerService接口,声明getCustomerAll()方法、addCustomer()方法、modifyCustomer()方法和deleteCustomer()方法。

在com.mhys.demo.service包下创建CustomerServiceImpl类,实现CustomerService接口,实现接口4个方法。

com.mhys.demo.service包下创建LinkmanService接口,声明getLinkmanAll()方法、addLinkman()方法、modifyLinkman()方法和deleteLinkman()方法。

在com.mhys.demo.service包下创建LinkmanServiceImpl类,实现LinkmanService接口,实现接口4个方法。

在com.mhys.demo.advice包下创建LoggerAdvice通知类,定义切入点,声明loggerBeforeAdvice()方法作为环绕增强。

在com.mhys.demo.advice包下创建TransactionAdvice通知类,定义切入点,声明transactionBefor()方法、transactionAfterReturning()方法和transactionAfter()方法。

在com.mhys.demo.test包下编写测试类。

3.4.3 实践练习

总结

Spring AOP是OOP的补充,它也提供了模块化。在面向对象编程中,关键的单元是对象,AOP的关键单元是切面。

通知(advice)是在程序中想要应用在其他模块中的横切关注点的实现。Advice主要有以下5种类型:前置通知、后置通知(After Retuning Advice)、异常拦截通知(After Throwing Advice)、最终通知(After Advice)、围绕通知(Around Advice)

Spring企业级程序设计 • 【第3章 面向切面编程】的更多相关文章

  1. Spring(三)--AOP【面向切面编程】、通知类型及使用、切入点表达式

    1.概念:Aspect Oriented Programming 面向切面编程 在方法的前后添加方法   2.作用:本质上来说是一种简化代码的方式      继承机制      封装方法      动 ...

  2. Spring之控制反转——IoC、面向切面编程——AOP

      控制反转——IoC 提出IoC的目的 为了解决对象之间的耦合度过高的问题,提出了IoC理论,用来实现对象之间的解耦. 什么是IoC IoC是Inversion of Control的缩写,译为控制 ...

  3. Spring详解(五)------面向切面编程

    .AOP 什么? AOP(Aspect Oriented Programming),通常称为面向切面编程.它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的 ...

  4. spring入门(四)【面向切面编程】

    开发过程中很多时候会用到日志.事务等操作,这些操作如果要写在业务代码中会相当麻烦,这时就会用到面向切面编程(AOP),AOP作为一种编程思想,和OOP有着不同的侧重点,面向对象侧重于万事万物皆对象,而 ...

  5. Spring框架(四)AOP面向切面编程

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  6. Spring学习手札(二)面向切面编程AOP

    AOP理解 Aspect Oriented Program面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 但是,这种说法有些片面,因为在软件工程中,AOP的价值体现的并 ...

  7. Spring详解篇之 AOP面向切面编程

    一.概述 Aop(aspect oriented programming面向切面编程),是spring框架的另一个特征.AOP包括切面.连接点.通知(advice).切入点(pointCut) . 1 ...

  8. 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  9. Spring总结六:AOP(面向切面编程)

    概述: AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术.它是一种新的 ...

随机推荐

  1. ACE_Message_Block实现浅析

    ACE_Message_Block实现浅析1. 概述ACE_Message_Block是ACE中很重要的一个类,和ACE框架中的重要模式的实现 如ACE_Reactor, ACE_Proactor, ...

  2. Linux 双网卡绑定及Bridge

    Linux 双网卡绑定及Bridge 阅读(5,202) 一:linux操作系统下双网卡绑定有七种模式.现在一般的企业都会使用双网卡接入,这样既能添加网络带宽,同时又能做相应的冗余,可以说是好处多多. ...

  3. spring-cloud-alibaba-dependencies版本问题

    org.springframework.cloud的spring-cloud-alibaba-dependencies管理的nacos最新版本是0.9.0.RELEASE,已经不再维护了,用起来有版本 ...

  4. 【Java基础】transient关键字

    1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过 ...

  5. 基于Annotation(注解)的装配

    一.常用注解 1.@Component 是一种通用注解,可用于任何Bean 2.@Repository 通常用于注解DAO层类,即持久层 3.@Service 通常用于注解Service类,即服务层 ...

  6. 11.Vue.js-事件处理器

    事件监听可以使用 v-on 指令: <div id="app"> <button v-on:click="counter += 1">增 ...

  7. 【手帐】Bullet Journal教程

    最近觉得自己的日程记录本有待提高,于是从今年开始开始入坑了手帐. *内容源自Bullet Journal官网.https://bulletjournal.com/pages/learn 快速笔记 Bu ...

  8. 网络访问控制列表ACL(读懂这篇就基本够了,后面有配置案例)

    一.访问控制列表是什么? 访问控制列表(ACL)是一种基于包过滤的访问控制技术,它可以根据设定的条件对接口上的数据包进行过滤,允许其通过或丢弃.访问控制列表被广泛地应用于路由器和三层交换机,借助于访问 ...

  9. WebDriver驱动下载地址

    chrome的webdriver: http://chromedriver.storage.googleapis.com/index.html Firefox驱动下载地址为:https://githu ...

  10. 一文掌握 Python 的描述符协议

    描述符介绍 描述符本质就是一个新式类,在这个新式类中,至少要实现了__get__(),__set__(),__delete__()中的一个.这也被称为描述符协议. class Myclass(obje ...