AOP面向切面编程、IOC控制反转/DI依赖注入

 

首先控制反转和面向切面编程是spring的核心机制,由于控制反转不好理解,因此有人提出依赖注入的概念,其实依赖注入是控制反转的一种方式,但现在大家默认控制反转等同于依赖注入

一.控制反转:控制反转是指spring容器通过依赖注入的方式使得创建依赖对象的控制权由对象转移到spring容器。举个例子:

我们有一个明星,要举办演唱会,在他唱歌之前有记者要采访他,通常我们的做法是创建一个明星类,在明星类里面new一个记者类,或者将记者类作为构造器的参数传入。如下图所示

在这里对象依赖的对象是由自己创建的。使用spring之后,reporter对象不再由superStar来创建而是交给spring容器来创建和管理,如下图:

我们在spring的配置文件中配置superstar和reporter两个bean,并把reporter注入到supers中,这样我们在superStard对象中不需要再自己去new一个reporter了,spring容器会帮我们创建。这就是控制反转,对象依赖ioc容器注入依赖的对象。实现解耦合。

二.面向切面编程

1)aspect(切面):实现了cross-cutting功能,是针对切面的模块。最常见的是logging模块,这样,程序按功能被分为好几层,如果按传统的继承的话,商业模型继承日志模块的话根本没有什么意义,而通过创建一个logging切面就可以使用AOP来实现相同的功能了。

2)jointpoint(连接点):连接点是切面插入应用程序的地方,该点能被方法调用,而且也会被抛出意外。连接点是应用程序提供给切面插入的地方,可以添加新的方法。比如以上我们的切点可以认为是findInfo(String)方法。

3)advice(处理逻辑):advice是我们切面功能的实现,它通知程序新的行为。如在logging里,logging advice包括logging的实现代码,比如像写日志到一个文件中。advice在jointpoint处插入到应用程序中。以上我们在MyHandler.java中实现了advice的功能

4)pointcut(切点):pointcut可以控制你把哪些advice应用于jointpoint上去,通常你使用pointcuts通过正则表达式来把明显的名字和模式进行匹配应用。决定了那个jointpoint会获得通知。

上面提到的例子中,记者在明星开场前进行采访,在明星演唱结束时报道,我们可以在superstar的singing方法前去调用reporter的interview方法,但我们发现这样我们的类会比较混乱,我们不希望在superstar的方法里看到reporter的方法,这时我们就需要面向切面编程AOP的帮忙了

我们可以将reporter配置成一个切面,通过配置的方式插入superstar中,完成采访任务,如下图:

内容大纲:

  • 描述一下Spring AOP?
  • 在Spring AOP中关注点(concern)和横切关注点(cross-cutting concern)有什么不同?
  • AOP有哪些可用的实现?
  • Spring中有哪些不同的通知类型(advice types)?
  • Spring AOP 代理是什么?
  • 引介(Introduction)是什么?
  • 连接点(Joint Point)和切入点(Point Cut)是什么?
  • 织入(Weaving)是什么?

描述一下Spring AOP

Spring AOP(Aspect Oriented Programming,面向切面编程)是OOPs(面向对象编程)的补充,它也提供了模块化。在面向对象编程中,关键的单元是对象,AOP的关键单元是切面,或者说关注点(可以简单地理解为你程序中的独立模块)。一些切面可能有集中的代码,但是有些可能被分散或者混杂在一起,例如日志或者事务。这些分散的切面被称为横切关注点。一个横切关注点是一个可以影响到整个应用的关注点,而且应该被尽量地集中到代码的一个地方,例如事务管理、权限、日志、安全等。
AOP让你可以使用简单可插拔的配置,在实际逻辑执行之前、之后或周围动态添加横切关注点。这让代码在当下和将来都变得易于维护。如果你是使用XML来使用切面的话,要添加或删除关注点,你不用重新编译完整的源代码,而仅仅需要修改配置文件就可以了。
Spring AOP通过以下两种方式来使用。但是最广泛使用的方式是Spring AspectJ 注解风格(Spring AspectJ Annotation Style)

  • 使用AspectJ 注解风格
  • 使用Spring XML 配置风格

在Spring AOP中关注点和横切关注点有什么不同?

关注点是我们想在应用的模块中实现的行为。关注点可以被定义为:我们想实现以解决特定业务问题的方法。比如,在所有电子商务应用中,不同的关注点(或者模块)可能是库存管理、航运管理、用户管理等。
横切关注点是贯穿整个应用程序的关注点。像日志、安全和数据转换,它们在应用的每一个模块都是必须的,所以他们是一种横切关注点。

AOP有哪些可用的实现?

基于Java的主要AOP实现有:

  1. AspectJ
  2. Spring AOP
  3. JBoss AOP

在维基百科上你可以找到一个AOP实现的大列表

Spring中有哪些不同的通知类型

通知(advice)是你在你的程序中想要应用在其他模块中的横切关注点的实现。Advice主要有以下5种类型:

  1. 前置通知(Before Advice): 在连接点之前执行的Advice,不过除非它抛出异常,否则没有能力中断执行流。使用 @Before 注解使用这个Advice。
  2. 返回之后通知(After Retuning Advice): 在连接点正常结束之后执行的Advice。例如,如果一个方法没有抛出异常正常返回。通过 @AfterReturning 关注使用它。
  3. 抛出(异常)后执行通知(After Throwing Advice): 如果一个方法通过抛出异常来退出的话,这个Advice就会被执行。通用 @AfterThrowing 注解来使用。
  4. 后置通知(After Advice): 无论连接点是通过什么方式退出的(正常返回或者抛出异常)都会执行在结束后执行这些Advice。通过 @After 注解使用。
  5. 围绕通知(Around Advice): 围绕连接点执行的Advice,就你一个方法调用。这是最强大的Advice。通过 @Around注解使用。

Spring AOP 代理是什么?

代理是使用非常广泛的设计模式。简单来说,代理是一个看其他像另一个对象的对象,但它添加了一些特殊的功能
Spring AOP是基于代理实现的。AOP 代理是一个由 AOP 框架创建的用于在运行时实现切面协议的对象
Spring AOP默认为 AOP 代理使用标准的 JDK 动态代理。这使得任何接口(或者接口的集合)可以被代理。Spring AOP 也可以使用 CGLIB 代理。这对代理类而不是接口是必须的。
如果业务对象没有实现任何接口那么默认使用CGLIB

引介(Introduction)是什么?

引介让一个切面可以声明被通知的对象实现了任何他们没有真正实现的额外接口,而且为这些对象提供接口的实现
使用 @DeclareParaents 注解来生成一个引介。
更多详情,请参考 官方文档

连接点(Joint Point)和切入点(Point cut)是什么?

连接点是程序执行的一个点。例如,一个方法的执行或者一个异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。举例来说,所有定义在你的 EmpoyeeManager 接口中的方法都可以被认为是一个连接点,如果你在这些方法上使用横切关注点的话。
切入点(切入点)是一个匹配连接点的断言或者表达式。Advice 与切入点表达式相关联,并在切入点匹配的任何连接点处运行(比如,表达式 execution(* EmployeeManager.getEmployeeById(...)) 可以匹配 EmployeeManager 接口的 getEmployeeById() )。由切入点表达式匹配的连接点的概念是 AOP 的核心。Spring 默认使用 AspectJ 切入点表达式语言。

什么是织入(weaving)?

Spring AOP 框架仅支持有限的几个 AspectJ 切入点的类型,它允许将切面运用到在 IoC 容器中声明的 bean 上。如果你想使用额外的切入点类型或者将切面应用到在 Spring IoC 容器外部创建的类,那么你必须在你的 Spring 程序中使用 AspectJ 框架,并且使用它的织入特性。
织入是将切面与外部的应用类型或者类连接起来以创建通知对象(adviced object)的过程。这可以在编译时(比如使用 AspectJ 编译器)、加载时或者运行时完成。Spring AOP 跟其他纯 Java AOP 框架一样,只在运行时执行织入。在协议上,AspectJ 框架支持编译时和加载时织入。
AspectJ 编译时织入是通过一个叫做 ajc 特殊的 AspectJ 编译器完成的。它可以将切面织入到你的 Java 源码文件中,然后输出织入后的二进制 class 文件。它也可以将切面织入你的编译后的 class 文件或者 Jar 文件。这个过程叫做后编译时织入(post-compile-time weaving)。在 Spring IoC 容器中声明你的类之前,你可以为它们运行编译时和后编译时织入。Spring 完全没有被包含到织入的过程中。更多关于编译时和后编译时织入的信息,请查阅 AspectJ 文档。
AspectJ 加载时织入(load-time weaving, LTW)在目标类被类加载器加载到JVM时触发。对于一个被织入的对象,需要一个特殊的类加载器来增强目标类的字节码。AspectJ 和 Spring 都提供了加载时织入器以为类加载添加加载时织入的能力。你只需要简单的配置就可以打开这个加载时织入器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值