1、什么是面向切面编程

AOP(Aspect-Oriented Programming), 即面向切面编程, 它与 OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与 OOP 不同的抽象软件结构的视角,也可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系,而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。使用“横切”技术。

AOP把软件系统分为两个部分:核心关注点(核心业务逻辑横切关注点(横向的通用逻辑。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。

2、Spring对AOP的支持

Spring提供了四种类型的AOP支持

  1. 经典的基于代理的AOP
  2. @AspectJ注解驱动的切面
  3. 纯POJO切面
  4. 注入式AspectJ切面

前三种都是Spring AOP现实的变体、Spring AOP构建在动态代理的基础之上、因此,Spring对AOP的支持局限于方法拦截

3、AOP的相关概念

1.通知(Advice) 通知定义了在切入点代码执行时间点附近需要做的工作。

Spring支持五种类型的通知:

  • @Before(前置通知) org.apringframework.aop.MethodBeforeAdvice
  • @AfterReturning(后置通知) org.springframework.aop.AfterReturningAdvice
  • @AfterThrowing(异常抛出) org.springframework.aop.ThrowsAdvice
  • @Arround(环绕通知) org.aopaliance.intercept.MethodInterceptor
  • @Introduction(引入) org.springframework.aop.IntroductionInterceptor

2.连接点(Joinpoint) 程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法调用时、异常抛出时、方法返回后等等。

3.切入点(Pointcut) 通知定义了切面要发生的“故事”,连接点定义了“故事”发生的时机,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,Spring中允许我们方便的用正则表达式来指定。

4.切面(Aspect) 通知、连接点、切入点共同组成了切面:时间、地点和要发生的“故事”。

5.引入(Introduction) 引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)。

6.目标(Target) 即被通知的对象,如果没有AOP,那么通知的逻辑就要写在目标对象中,有了AOP之后它可以只关注自己要做的事,解耦合!

7.代理(proxy) 应用通知的对象,详细内容参见设计模式里面的动态代理模式。

8.织入(Weaving) 把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:

  1. 编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器;
  2. 类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码;
  3. 运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术。

4、相关知识点

AOP 有哪些实现方式?

实现 AOP 的技术,主要分为两大类: 静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强; 编译时编织(特殊编译器实现) 类加载时编织(特殊的类加载器实现)。 动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。 JDK 动态代理 CGLIB

Spring AOP and AspectJ AOP 有什么区别?

Spring AOP 基于动态代理方式实现;AspectJ 基于静态代理方式实现。 Spring AOP 仅支持方法级别的 PointCut;提供了完全的 AOP 支持,它还支持属性级别的 PointCut。

如何理解 Spring 中的代理?

将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。

指出在 spring aop 中 concern 和 cross-cutting concern 的不同之处。

concern 是我们想要在应用程序的特定模块中定义的行为。它可以定义为我们想要实现的功能。cross-cutting concern 是一个适用于整个应用的行为,这会影响整个应用程序。例如,日志记录,安全性和数据传输是应用程序几乎每个模块都需要关注的问题,因此它们是跨领域的问题。

5、使用注释创建切面

@Aspect
@Component
public class Spring4AopConfig {/*** execution 用于匹配方法执行的连接点;* within 用于匹配指定类型内的方法执行;*/
//  @Pointcut("within(com.spr.demo.service..*)")
//  public void commonServiceLogger(){}@Pointcut(value = "execution(** com.spr.demo.controller.AopCpntroller.*(..))")public void commonExecution(){}@Before("commonExecution()")public void startMethod(JoinPoint point) {System.out.println(point.getSignature().getName() + "前置通知...");}@AfterReturning(pointcut = "commonExecution()",returning="result")public void afterMethod(JoinPoint point,Object result) {System.out.println(point.getSignature().getName() + "后置通知:" + result);}@AfterThrowing(pointcut = "commonExecution()",throwing = "e")public void throwMethod(JoinPoint point, Throwable e) {System.out.println(point.getSignature().getName() + "异常通知:" + e);}/*** joinpoint和proceedingjoinpoint区别* joinpoint:public interface JoinPoint {  String toString();         //连接点所在位置的相关信息  String toShortString();     //连接点所在位置的简短相关信息  String toLongString();     //连接点所在位置的全部相关信息  Object getThis();         //返回AOP代理对象  Object getTarget();       //返回目标对象  Object[] getArgs();       //返回被通知方法参数列表  Signature getSignature();  //返回当前连接点签名  SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置  String getKind();        //连接点类型  StaticPart getStaticPart(); //返回连接点静态部分  }  * proceedingjoinpoint:* public interface ProceedingJoinPoint extends JoinPoint {  public Object proceed() throws Throwable;  public Object proceed(Object[] args) throws Throwable;  }JoinPoint.StaticPart:提供访问连接点的静态部分,如被通知方法签名、连接点类型等:public interface StaticPart {  Signature getSignature();    //返回当前连接点签名  String getKind();          //连接点类型  int getId();               //唯一标识  String toString();         //连接点所在位置的相关信息  String toShortString();     //连接点所在位置的简短相关信息  String toLongString();     //连接点所在位置的全部相关信息  } 环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。*/@Around("commonExecution()")
//  public void aroundMethod(ProceedingJoinPoint jp,Throwable e){public void aroundMethod(ProceedingJoinPoint point){try {System.out.println("< 环绕通知开始执行 >...");Object proceed = point.proceed();System.out.println("< 环绕通知执行完成 > : " + point.getSignature().getName() + ","+point.getSignature().getDeclaringTypeName()+","+proceed);} catch (Throwable e) {System.err.println("< 环绕通知异常 > : " + e.getMessage());}}}

如果不想要使用@Component注解加载切面,也可以通过组件加载:

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConfigCenter {@Beanpublic Spring4AopConfig spring4AopConfig() {return new Spring4AopConfig();}
}

6、通过注解引入新功能

使用@DeclareParents注解,将接口引入到Spring Bean中。

  @DeclareParents注解由三部分组成:

    1)value属性指定了哪种类型的bean要引入该接口。加号(+)表示是该类型的所有子类型,而不是该类型本身。

    2)defaultImpl属性指定了为引入功能提供实现的类。

    3)@DeclareParents注解所标注的静态属性指明了要引入的接口。

EncoreableIntroducer是一个切面,同时声明它是一个bean。但是,它与我们 之前所创建的切面不同,它并没有提供前置、后置或环绕通知,而是 通过@DeclareParents注解,将Encoreable接口引入 到Performance bean中:

// 创建一个接口
public interface Encoreable {void performEncore();}// 实现接口
public class DefaultEncoreable implements Encoreable {@Overridepublic void performEncore() {System.out.println("接口实现");}
}//新建切面
@Aspect
@Component
public class EncoreableIntroducer {@DeclareParents(value = "concert2.Performance+", defaultImpl = DefaultEncoreable.class)public static Encoreable encoreable;
}

7、注入AspectJ切面

虽然Spring AOP能够满足许多应用的切面需求,但是与AspectJ相比,Spring AOP 是一个功能比较弱的AOP解决方案。AspectJ提供了Spring AOP所不能支持的许多类型的切点。

//定义切面
public aspect CriticAspect {public CriticAspect(){}//定义切点pointcut performance():execution(* perform(..));afterReturning : performance(){System.out.println(criticismEngine.getCriticism());}private CriticismEngine criticismEngine;// 注入criticismEnginepublic void setCriticismEngine(CriticismEngine criticismEngine){this.criticismEngine = criticismEngine;}
}public class CriticismEngineImpl extends CriticismEngine {public CriticismEngineImpl(){}private String[] criticismPool;@Overridepublic String getCriticism(){int i = (int)(Math.random() * criticismPool.length);return criticismPool[i];}public void setCriticismPool(String[] criticismPool){this.criticismPool = criticismPool;}
}

Spring4详解系列(四)面向切面的Spring相关推荐

  1. spring(4)面向切面的Spring(AOP)

    [0]README 1)本文部分文字描述转自:"Spring In Action(中/英文版)",旨在review  "spring(4)面向切面的Spring(AOP) ...

  2. 《Spring实战》读书笔记-第4章 面向切面的Spring

    <Spring实战>是学习Spring框架的一本非常经典的书籍,之前阅读了这本书,只是在书本上写写画画,最近整理了一下<Spring实战>的读书笔记,通过博客的方式进行记录分享 ...

  3. 面向切面的 Spring —— 什么是面向切面编程?

    Q1:面向切面编程(AOP)解决什么问题? A1:把横切关注点与业务逻辑相分离. Q2:什么是横切关注点? A2:在软件开发中,散布于应用中多处的功能. 日志是应用切面的常见范例,但并不是切面适用的唯 ...

  4. Spring实战 | 第一部分 Spring的核心(第四章 面向切面的Spring)

    第四章 面向切面编程 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 AspectJ是一个面向切面的框架,它扩展了java语言.AspectJ定义 ...

  5. spring boot 503_Spring实战读书笔记第4章 面向切面的Spring

    本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 在软件开发中,散布于应用中多的功能被称为横切关注点(cross-cutting con ...

  6. 面向切面的Spring

    2019独角兽企业重金招聘Python工程师标准>>> 前言 在软件开发中,散布于应用中多处的功能被称为横切关注点.这些横切关注点从概念上是与应用的业务逻辑相分离的.把这些横切关注点 ...

  7. 【Spring实战学习笔记】第4章 面向切面的Spring

    目录 4.1 什么是面向切面编程 4.2 通过切点来选择连接点 4.3 使用注解创建切面 4.4 在XML中声明切面 4.5 注入AspectJ切面 4.6 小结 在软件开发中,散布于应用中多处的功 ...

  8. Spring4详解系列(一)Spring之旅

    1.Spring的核心 Spring可以做很多事,提供了很多企业级开发的功能,但是这些功能的底层都依赖于它的两个核心特性: ①DI(Dependency Injection)依赖注入,指容器复制创建和 ...

  9. Handler详解系列(四)——利用Handler在主线程与子线程之间互发消息,handler详解...

    MainActivity如下: package cc.c;import android.app.Activity; import android.os.Bundle; import android.o ...

最新文章

  1. Django之Xadmin
  2. Pretty girl,你一定要去旅行
  3. 如何在MVCsheet表单页面的后台取到页面自定义字段的值?
  4. jdk1.6 改 jdk1.7或jdk1.8(改回也可以)(图文详解)
  5. oracle如何在本地建库,oracle在本地建库
  6. FD.io VPP:探究分段场景下vlib_buf在收发包的处理(dpdk_plugin.so)、rte_mbuf与vlib_buf 关系
  7. strcpy vs memcpy
  8. springamqp_SpringAMQP
  9. 穿越沙漠问题c语言算法,穿越沙漠问题---递推法
  10. 软件测试的底层逻辑是什么?
  11. Nifi从入门到精通(一)之 数据存储
  12. win10计算器rsh_win10 自带计算器快捷键有哪些_windows10计算器快捷键汇总
  13. 组合数计算(从1000到1e9的组合数各类求法)
  14. Sql 中text类型字段判断是否为空
  15. 丽丽的redhat终于可以上网了
  16. QQ 聊天机器人API
  17. Centos7.5系统部署禅道协调管理系统以及配置优化
  18. windows11如何退回windows10,手把手,突然觉得我不适合win11
  19. 在Arcmap中,如何“让标注和注记的字体,以及符号化后的符号大小随着比例尺大小的变换而变换”???
  20. 关于VC++调试项 Multi-threaded Debug DLL的问题。

热门文章

  1. Ubuntu关机异常慢的解决方法
  2. 常见的Linux操作系统
  3. scrapy框架爬取建设行业数据实例(思路整理)
  4. irobot擦地机器人故障_简单修理irobot 380T拖地机器人 后退转圈故障
  5. 通过 iframe引用的vue文件之间的方法互调
  6. 从B站商业化看社区变现能力
  7. 贴片式LED正负极怎么看
  8. linux下查看pid namespace的方法
  9. 第三方软件测试报告有那些——软件检测报告有什么类型
  10. windows10 提示系统激活失败,报错为:激活错误0xcc004f012