1.AOP的概念

  AOP(Aspect Oriented Programming 面向切面编程),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

常用于日志记录,性能统计,安全控制,事务处理,异常处理等等。

2.AOP的作用、优势及其实现方式

作用:在程序运行期间,不修改源码对已有方法进行增强。

优势:减少重复代码,提高开发效率维护方便。

实现方式:使用动态代理技术

3.AOP的相关术语

(1)Joinpoint(连接点):

  所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。

(2)Pointcut(切入点):

  所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。

(3)Advice(通知/增强):

  所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

(4)Introduction(引介):

  引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。

(5)Target(目标对象):

  代理的目标对象。

(6)Weaving(织入):

  是指把增强应用到目标对象来创建新的代理对象的过程。

  spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

(7)Proxy(代理):

  一个类被 AOP 织入增强后,就产生一个结果代理类。

(8)Aspect(切面):

  是切入点和通知(引介)的结合。

4.学习 spring中的 AOP要明确的事

a、开发阶段(我们做的)

  编写核心业务代码(开发主线):大部分程序员来做,要求熟悉业务需求。
  把公用代码抽取出来,制作成通知。(开发阶段最后再做):AOP 编程人员来做。在配置文件中,声明切入点与通知间的关系,即切面。:AOP 编程人员来做。

b、运行阶段(Spring 框架完成的)

  Spring 框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。

5.AOP的五种通知类型

(1)前置通知[Before advice]:在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。 
(2)正常返回通知[After returning advice]:在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。 
(3)异常返回通知[After throwing advice]:在连接点抛出异常后执行。 
(4)返回通知[After (finally) advice]:在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。 
(5)环绕通知[Around advice]:

  环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类型,能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。spring中的环绕通知:它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。

6.Spring AOP使用案例

<1>案例目录结构

<2>账户的业务层接口及其实现类

IAccountService.java

package lucky.service;/*** 账户的业务层接口*/
public interface IAccountService {/*** 模拟保存账户*/void saveAccount();/*** 模拟更新账户* @param i*/void updateAccount(int i);/*** 删除账户* @return*/int  deleteAccount();
}

AccountServiceImpl.java

package lucky.service.impl;
import lucky.service.IAccountService;/*** 账户的业务层实现类*/
public class AccountServiceImpl implements IAccountService {public void saveAccount() {System.out.println("执行了保存");}public void updateAccount(int i) {System.out.println("执行了更新"+i);}public int deleteAccount() {System.out.println("执行了删除");return 0;}
}

<3>日志工具类(模拟的,并不是实际)

package lucky.utils;import org.aspectj.lang.ProceedingJoinPoint;/*** 用于记录日志的工具类**/
public class LoggerUtil {/*** 用于打印日志,计划让其在切入点方法执行之前执行(切入点方法就是业务层方法)*/public void printLog(){System.out.println("Logger类中的pringLog方法开始记录日志了。。。");}/*** 前置通知*/public  void beforePrintLog(){System.out.println("前置通知Logger类中的beforePrintLog方法开始记录日志了。。。");}/*** 后置通知*/public  void afterReturningPrintLog(){System.out.println("后置通知Logger类中的afterReturningPrintLog方法开始记录日志了。。。");}/*** 异常通知*/public  void afterThrowingPrintLog(){System.out.println("异常通知Logger类中的afterThrowingPrintLog方法开始记录日志了。。。");}/*** 最终通知*/public  void afterPrintLog(){System.out.println("最终通知Logger类中的afterPrintLog方法开始记录日志了。。。");}/*** 环绕通知* 问题:*      当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了。* 分析:*      通过对比动态代理中的环绕通知代码,发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有。* 解决:*      Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法。*      该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用。** spring中的环绕通知:*      它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。*/public Object aroundPringLog(ProceedingJoinPoint pjp){Object rtValue = null;try{Object[] args = pjp.getArgs();//得到方法执行所需的参数
System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置");rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置");return rtValue;}catch (Throwable t){System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常");throw new RuntimeException(t);}finally {System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");}}
}

<4>bean.xml

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--目的说明:要给AccountServiceImpl类进行增强,使得执行这个类中的任何方法都记录一下日志--><!--配置spring的ioc,把service对象配置进来--><bean id ="accountService" class="lucky.service.impl.AccountServiceImpl"></bean><!--spring中基于XML的AOP配置步骤1、把通知Bean也交给spring来管理2、使用aop:config标签表明开始AOP的配置3、使用aop:aspect标签表明配置切面id属性:是给切面提供一个唯一标识ref属性:是指定通知类bean的Id。4、在aop:aspect标签的内部使用对应标签来配置通知的类型我们现在示例是让printLog方法在切入点方法执行之前之前:所以是前置通知aop:before:表示配置前置通知method属性:用于指定Logger类中哪个方法是前置通知pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强切入点表达式的写法:关键字:execution(表达式)表达式:访问修饰符  返回值  包名.包名.包名...类名.方法名(参数列表)标准的表达式写法:public void com.itheima.service.impl.AccountServiceImpl.saveAccount()访问修饰符可以省略void com.itheima.service.impl.AccountServiceImpl.saveAccount()返回值可以使用通配符,表示任意返回值* com.itheima.service.impl.AccountServiceImpl.saveAccount()包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.* *.*.*.*.AccountServiceImpl.saveAccount())包名可以使用..表示当前包及其子包* *..AccountServiceImpl.saveAccount()类名和方法名都可以使用*来实现通配* *..*.*()参数列表:可以直接写数据类型:基本类型直接写名称           int引用类型写包名.类名的方式   java.lang.String可以使用通配符表示任意类型,但是必须有参数可以使用..表示有无参数均可,有参数可以是任意类型全通配写法:* *..*.*(..)实际开发中切入点表达式的通常写法:切到业务层实现类下的所有方法* com.itheima.service.impl.*.*(..)--><!--配置logger类--><bean id="logger" class="lucky.utils.LoggerUtil"></bean><!--配置AOP--><aop:config><!-- 配置切入点表达式 id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容此标签写在aop:aspect标签内部只能当前切面使用。它还可以写在aop:aspect外面,此时就变成了所有切面可用--><aop:pointcut id="pt1" expression="execution(* lucky.service.impl.*.*(..))"></aop:pointcut><!--配置切面 --><aop:aspect id="logAdvice" ref="logger"><!-- 配置通知的类型,并且建立通知方法和切入点方法的关联--><!--<aop:before method="printLog" pointcut="execution(* lucky.service.impl.*.*(..))"></aop:before>--><!--配置前置通知:在切入点方法执行之前执行--><!--<aop:before method="beforePrintLog" pointcut-ref="pt1" ></aop:before>--><!--配置后置通知:在切入点方法正常执行之后值。它和异常通知永远只能执行一个--><!--<aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>--><!-- 配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>--><!-- 配置最终通知:无论切入点方法是否正常执行它都会在其后面执行<aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>--><!-- 配置环绕通知 详细的注释请看Logger类中--><aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around></aop:aspect></aop:config>
</beans>

<5>测试类

import lucky.service.IAccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AOPTest01 {@Testpublic void testAop(){//1.获取容器ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");//2.获取对象IAccountService as = (IAccountService)ac.getBean("accountService");//3.执行方法
        as.saveAccount();/*as.updateAccount(1);as.deleteAccount();*/}
}

调用AOPTest01这个类中的testAop()方法,控制台输出

转载于:https://www.cnblogs.com/luckyplj/p/11323119.html

11 Sping框架--AOP的相关概念及其应用相关推荐

  1. spring框架 AOP核心详解

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  2. 大数据WEB阶段Spring框架 AOP面向切面编程(一)

    Spring - AOP面向切面编程(一) 一.代理模式概述 代理的特点:(目标对象即被代理者) 实现和目标对象相同的接口 具备和目标对象的方法 代理者不仅要做目标对象的方法 , 还要做一些额外的操作 ...

  3. java day59【 AOP 的相关概念[理解] 、 Spring 中的 AOP[掌握] 、 Spring 整合 Junit[掌握] 】...

    第1章 AOP 的相关概念[理解] 1.1AOP 概述 1.1.1 什么是 AOP 1.1.2 AOP 的作用及优势 1.1.3 AOP 的实现方式 1.2AOP 的具体应用 1.2.1 案例中问题 ...

  4. Spring框架AOP源码剖析

    今天我要和大家分享的是 AOP(Aspect-Oriented Programming)这个东西的源码剖析,作为多年的开发者,想必大家在面试的时候都被问过,你知道Spring框架AOP的底层实现机制吗 ...

  5. ajax的11个框架

    本文转载自 : www.iteye.com AJAX(Asynchronous JavaScript and XML,异步 JavaScript 和 XML),是创建交互式 Web 应用的主要开发技术 ...

  6. SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Asp ...

  7. Spring框架 AOP

    AOP(Aspect Oriented Programming) 原理 正常程序执行顺序都为纵向执行流程 ,在某一个步骤的前后,做一个前置通知 和后置通知,这个过程称为切面编程. 即:在原有的纵向执行 ...

  8. Spring框架 AOP面向切面编程(转)

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

  9. Spring框架----AOP的概念及术语

    1.什么是AOP AOP:全称是 Aspect Oriented Programming 即:面向切面编程 简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源 ...

最新文章

  1. dede 两种幻灯代码
  2. 使用VNC访问Linux桌面
  3. CSDN鸿蒙社区福利:HarmonyOS Beta 版内测资格申请
  4. DDD领域模型、贫血模型、充血模型概念总结
  5. m3u8手机批量转码_手机怎么把m3u8格式转换成mp4格式?
  6. 计算机丨浏览器访问出现DNS_PROBE_POSSIBLE解决方法
  7. easyui datebox 设置只读
  8. python解析json文件三种_Python解析json文件相关知识学习
  9. python加法运算符_python 入门之 – 基本运算符(七)
  10. 产业AI公司的简单调研
  11. FI-SAP财务成本知识点汇总
  12. CentOS程序包管理、上
  13. Nginx常用知识梳理(三)——windows环境下端口耗尽问题
  14. 我是新来的请多多关照
  15. 微应用 qiankun 项目搭建
  16. Git如何上传代码到远程仓库(GiteeGithub)
  17. 一文看懂 LSTM(Long Short-Term Memory)
  18. [wayfarer]PetShop之业务逻辑层设计
  19. 达梦数据库大小写敏感介绍
  20. markdown快速插入图片技巧

热门文章

  1. centos7下安装libiconv失败
  2. Ubuntu系列10.04、11.04、12.04等虚拟机中安装VMware Tools
  3. 跟着百度学PHP[4]OOP面对对象编程-16-switch逻辑就语句
  4. hadoop2.0初识1.2
  5. SOA面向服务架构——SOA的概念
  6. 站内搜索 调用方法 (谷歌 百度 雅虎)
  7. 面向对象编程(OOP)和函数式编程(FP)的思考
  8. Python中的问卷调查(华为机测题)
  9. js等待5秒后执行_厦门同安首台智能垃圾分类回收柜机投用 扫二维码5秒后回收变现...
  10. 如何将原图和json融合_用 base64 进行图片和字符串互转,并保存至 json