一、什么是AOP

引用一下维基百科的定义

面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计剖面导向程序设计)是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进行进一步分离,以提高程序代码的模块化程度。通过在现有代码基础上增加额外的通知(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块进行统一管理与装饰,如“对所有方法名以‘set*’开头的方法添加后台日志”。该思想使得开发人员能够将与代码核心业务逻辑关系不那么密切的功能(如日志功能)添加至程序中,同时又不降低业务代码的可读性。面向切面的程序设计思想也是面向切面软件开发的基础。

面向切面的程序设计将代码逻辑切分为不同的模块(即关注点(Concern),一段特定的逻辑功能)。几乎所有的编程思想都涉及代码功能的分类,将各个关注点封装成独立的抽象模块(如函数、过程、模块、类以及方法等),后者又可供进一步实现、封装和重写。部分关注点“横切”程序代码中的数个模块,即在多个模块中都有出现,它们即被称作“横切关注点(Cross-cutting concerns, Horizontal concerns)”。

日志功能即是横切关注点的一个典型案例,因为日志功能往往横跨系统中的每个业务模块,即“横切”所有有日志需求的类及方法体。而对于一个信用卡应用程序来说,存款、取款、帐单管理是它的核心关注点,日志和持久化将成为横切整个对象结构的横切关注点。

二、AOP相关术语

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

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

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

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

  • Target(目标对象): 代理的目标对象。

  • Weaving(织入): 是指把增强应用到目标对象来创建新的代理对象的过程。 spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。

  • Proxy(代理): 一个类被 AOP 织入增强后,就产生一个结果代理类。-

  • Aspect(切面): 是切入点和通知(引介)的结合。


三、使用注解实现spring AOP

首先是我们的业务逻辑类

public class MathCalculator {

	public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
} }

接着是我们的切面类

/**
* 切面类
* @author lfy
*
* @Aspect: 告诉Spring当前类是一个切面类
*
*/
@Aspect
public class LogAspects { //抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
public void pointCut(){}; //@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
} @After("com.atguigu.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
} //JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
} @AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
} /*@Around(value="pointCut()")
public void myAround(ProceedingJoinPoint joinPoint) {
// 方法之前,前置通知
System.out.println("《方法之前:前置通知");
try {
// 方法执行时
joinPoint.proceed(); // 执行方法
// 方法执行之后:后置通知
System.out.println("《方法执行之后:后置通知");
} catch (Throwable e) {
// 发生异常时
System.out.println("《发生异常时:异常通知");
} finally {
// 最终通知
System.out.println("《最终通知");
}
}*/ }

接着是我们的配置类:

/**
* AOP:【动态代理】
* 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式;
*
* 1、导入aop模块;Spring AOP:(spring-aspects)
* 2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
* 3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
* 通知方法:
* 前置通知(@Before):logStart:在目标方法(div)运行之前运行
* 后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
* 返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
* 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
* 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
* 4、给切面类的目标方法标注何时何地运行(通知注解);
* 5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
* 6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
* [7]、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
* 在Spring中很多的 @EnableXXX;
*
* 三步:
* 1)、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
* 2)、在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
* 3)、开启基于注解的aop模式;@EnableAspectJAutoProxy
*/
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP { //业务逻辑类加入容器中
@Bean
public MathCalculator calculator(){
return new MathCalculator();
} //切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}

最后是我们的测试类:

public class IOCTest_AOP {

	@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class); //1、不要自己创建对象
// MathCalculator mathCalculator = new MathCalculator();
// mathCalculator.div(1, 1);
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class); mathCalculator.div(1, 1); applicationContext.close();
} }

控制台打印结果:

div运行。。。@Before:参数列表是:{[1, 1]}
MathCalculator...div...
div结束。。。@After
div正常返回。。。@AfterReturning:运行结果:{1}

注释中已经解释的很详细了,不再赘述。


四、环绕通知

环绕通知的功能比较强大,它可以实现其他四种通知

具体代码也很同意理解,放开LogAspects中的myAround方法,为方便观察,可以注释掉其他四种通知.

我们写个测试方法测试一下。

这次我们除以0试试

mathCalculator.div(1, 0);

打印:

《方法之前:前置通知
MathCalculator...div...
《发生异常时:异常通知
《最终通知

注意:环绕通知需要执行目标方法,参数使用ProceedingJoinPoint joinPoint,其父类没有这个joinPoint.proceed(); /方法。

spring AOP注解实现的更多相关文章

  1. Spring AOP注解为什么失效?90%Java程序员不知道

    使用Spring Aop注解的时候,如@Transactional, @Cacheable等注解一般需要在类方法第一个入口的地方加,不然不会生效. 如下面几种场景 1.Controller直接调用Se ...

  2. Spring aop注解失效

    问题 在spring 中使用 @Transactional . @Cacheable 或 自定义 AOP 注解时,对象内部方法中调用该对象的其他使用aop机制的方法会失效. @Transactiona ...

  3. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

  4. spring aop注解配置

    spring aop是面向切面编程,使用了动态代理的技术,这样可以使业务逻辑的代码不掺入其他乱七八糟的代码 可以在切面上实现合法性校验.权限检验.日志记录... spring aop 用的多的有两种配 ...

  5. Spring AOP 注解和xml实现 --转载

    AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...

  6. spring Aop 注解

    个人理解: spring Aop 是什么:面向切面编程,类似于自定义拦截操作,支持拦截之前操作@Before,拦截之后操作@After,拦截环绕操作@Around. 什么情况下使用spring Aop ...

  7. Spring aop 注解参数说明

    在spring AOP中,需要使用AspectJ的切点表达式语言来定义切点. 关于Spring AOP的AspectJ切点,最重要的一点是Spring仅支持AspectJ切点指示器(pointcut ...

  8. 【学习笔记】Spring AOP注解使用总结

    Spring AOP基本概念 是一种动态编译期增强性AOP的实现 与IOC进行整合,不是全面的切面框架 与动态代理相辅相成 有两种实现:基于jdk动态代理.cglib Spring AOP与Aspec ...

  9. 6.spring:AOP(注解)

     spring Aop AOP面向切面编程,与OOP面向对象编程相辅相成 AOP中最基本的单元是切面 问题: 代码混乱:越来越多的业务需求(日志&验证)加入后,原有的业务方法急剧膨胀,每个方法 ...

  10. 转:Spring AOP 注解方式实现的一些“坑”

    使用过Spring AOP的注解方式实现,也入过不少坑,现在做一下记录,希望有同样需求的朋友可以少走弯路 使用之前还是先过一下官方文档吧,至少可以少走弯路,不用担心英文读不懂,其实只看代码例子就能理解 ...

随机推荐

  1. wordpress调用缩略图/特色图url

    调用缩略图的url <a href="<?php the_post_thumbnail_url( 'full' ); ?>"><?php the_po ...

  2. 【深入ASP.NET原理系列】--Asp.Net Mvc和Asp.Net WebForm实际上共用一套ASP.NET请求管道

    .NET FrameWork4在系统全局配置文件(如在如下目录中C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config) 中添加了一个名字叫Url ...

  3. [Codeforces 1242B]0-1 MST

    Description 题库链接 给你一张 \(n\) 个点的完全图,其中有 \(m\) 条边长度为 \(1\),其余全为 \(0\).问你这张图的最小生成树为多少. \(1\leq n\leq 10 ...

  4. LeetCode 685. Redundant Connection II

    原题链接在这里:https://leetcode.com/problems/redundant-connection-ii/ 题目: In this problem, a rooted tree is ...

  5. 4个MySQL优化工具AWR,帮你准确定位数据库瓶颈!(转载)

    对于正在运行的mysql,性能如何,参数设置的是否合理,账号设置的是否存在安全隐患,你是否了然于胸呢? 俗话说工欲善其事,必先利其器,定期对你的MYSQL数据库进行一个体检,是保证数据库安全运行的重要 ...

  6. redis 设置为只读模式

    数据库的只读模式,对于在系统出现重大故障,但是又不影响用户的查询操作还是很重要的 对于redis 设置只读模式需要分不同的场景 master-slave cluster single master-s ...

  7. Cogs 1632. 搬运工(二分图最小点覆盖)

    搬运工 ★ 输入文件:worker.in 输出文件:worker.out 简单对比 时间限制:1 s 内存限制:256 MB [题目描述] 小涵向小宇推荐了一款小游戏. 游戏是这样的,在一个n*n的地 ...

  8. 洛谷 P2312 解方程 题解

    P2312 解方程 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 [1,m][1,m] 内的整数解(\(n\) 和 \(m\) 均为 ...

  9. Eclipse安装jbpm插件

    1.1   eclipse mar 和neon有什么区别? Eclipse 是一个开放源代码的.基于Java的可扩展开发平台.就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境. . ...

  10. 仿站技术——获取和使用某些网站的iconfont图标字体

    前言: 很多前端新手在仿一些大型网站的时候经常遇到一个问题:该网站使用了图标字体——iconfont,虽然现在阿里有开源的iconfont库,但是还是没有原网站的效果(本人强迫症但非处女座).所以此文 ...