什么是 AOP?

什么是 AOP?

AOP(面向切面编程,Aspect-Oriented-Programming),可以说是OOP(面向对象编程,Object-Oriented-Programing)的完善和补充。OOP允许定义从上到下的关系,但并不适合定义从左到右的关系。比如日志功能。日志功能的代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。这种散布在各处的无关的代码被称之为横切(cross-cutting)代码,在面向对象的设计中,这种设计导致了大量代码的重复,出现冗余,提高了维护成本,而不利于各个模块的重用。

而AOP技术则恰恰相反,它是利用一种称之为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块中,并且将其命名为"Aspect",即切面。这所谓的"切面",简而言之,就是把那些个那些与业务无关的,却为业务模块所共同公共调用的逻辑或者责任封装起来,进而便于减少系统的重复代码量,并且能够降低模块间的耦合度,并有利于未来的可操作性和可维护性,降低了维护成本。

我们先来了解一下AOP的实现策略:

(1)Java SE动态代理:

使用动态代理可以为一个或多个接口在运行期动态生成实现对象,生成的对象中实现接口的方法时可以添加增强代码,从而实现AOP。缺点是只能针对接口进行代理,另外由于动态代理是通过反

射实现的,有时可能要考虑反射调用的开销。

(2)定制的类加载器

当需要对类的所有对象都添加增强,动态代理和字节码生成本质上都需要动态构造代理对象,即最终被增强的对象是由AOP框架生成,不是开发者new出来的。解决的办法就是实现自定义的类加载器,在一个类被加载时对其进行增强。JBoss就是采用这种方式实现AOP功能。

(3)字节码生成(CGLib 动态代理)

动态字节码生成技术是指在运行时动态生成指定类的一个子类对象,并覆盖其中特定方法,覆盖方法时可以添加增强代码,从而实现AOP。其常用工具是cglib。

(4)语言扩展

可以对构造方法和属性的赋值操作进行增强,AspectJ是采用这种方式实现AOP的一个常见Java语言扩展。

(5)代码生成

利用工具在已有代码基础上生成新的代码,其中可以添加任何横切代码来实现AOP。

AOP的使用场景

AOP框架的种类如下:

→AspectJ

→Spring AOP

→JBoss AOP

 

可以使用AOP可以做的事情有很多。

→ 最常见的就是记录日志,如在方法执行前后记录系统日志。

→ 再者就是性能监控,如在方法调用前后记录调用的时间,方法执行时间太长或超时报警。

→ 然后就是缓存代理,如缓存某个方法的返回值,下次执行该方法时候,就直接从缓存里获取。

→ 然后就是软件破解,如使用AOP修改软件的验证类的判断逻辑等等。

→ 然后就是工作流系统,工作流系统需要将业务代码和流程引擎代码混合在一起执行,那么我们可以使用AOP将其分离,并动态挂接业务。

→ 最后就是权限验证,方法执行前验证是否有权限执行当前方法,没有则抛出没有权限执行异常,由业务代码捕捉。

先来观察一下传统编码方式与使用aop的区别吧

日志处理

核心概念描述

我们再来描述AOP中常用的一些术语给大家哈:如 切点(Pointcut)、通知(Adivce)、连接点(Join point)、引入(Introduction)、织入(Weaving)、切面(Aspect)等。

AOP 的重要概念

简单例子

相比xml配置,基于注解的方式更加简洁方便。

@Aspect

public class SpringAOPDemo {

}

在applicationContext.xml中配置。

在切面类上使用Aspect,当然使用注解的话必须得在xml文件中先配置 aop:aspectj-autoproxy。

下面给出一个Spring AOP的.xml文件模板,名字叫做applicationContext.xml,之后的内容都在applicationContext.xml上进行扩展:

说下 Spring AOP原理

仔细看了前面段落的朋友就知道:Spring AOP 代理其实本质上就是由 Spring AOP 框架动态生成的一个对象而已,并且该对象可作为目标对象使用的,我们完全代理了目标对象了。Spring AOP 代理它包含了目标对象的全部方法,But Spring AOP 代理中的方法与目标对象的方法是存在差异的:Spring AOP 方法在特定切入点添加了增强逻辑处理,并且回调目标对象的方法。

代理的方法与目标对象的方法

Spring 的 AOP 代理是完全由 Spring 的 IoC 容器负责生成、管理的,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他 Bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。

AOP开发时,其中需要程序员参与的只有 3 个部分:

定义普通业务组件。

定义切入点,一个切入点可能横切多个业务组件。

定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。

为了理清关系,先来个UML类关系图。

Spring中主要的AOP组件

AOP核心概念

1、横切关注点

对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点

2、切面(aspect)

类是对物体特征的抽象,切面就是对横切关注点的抽象

3、连接点(joinpoint)

被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器

4、切入点(pointcut)

对连接点进行拦截的定义

5、通知(advice)

所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

6、目标对象

代理的目标对象

7、织入(weave)

将切面应用到目标对象并导致代理对象创建的过程

8、引入(introduction)

在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

举两个例子:

分别用配置文件和注解实现AOP

xml配置文件:

1. TestAspect:切面类

2. AServiceImpl:目标对象

3. BServiceImpl:目标对象

4. ApplicationContext:Spring配置文件

二、注解(Annotation)方式

TestAnnotationAspect

2. ApplicationContext:Spring配置文件

看到这里大家发现没有,使用注解少写了很多的代码,所以小编在这里推荐大家使用注解的方式。because省时省力。

JDK实现的动态代理

java 运行环境JDK,jdk中也给我们提供了动态代理,jdk中的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。InvocationHandler它是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。

Proxy利用InvocationHandler动态创建一个符合某一接口的实例,用来生成目标类的代理对象。

两种动态的代理方式

Spring是默认采取的动态代理机制实现AOP的,当然,在当动态代理不可用时候(代理类无接口)它就会使用CGlib的机制了。

Spring提供了两种方式来生成代理对象: 一个是JDK的Proxy,另一个就是Cglib了,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。Spring会自动选择使用那种方式,我们不用担心。此处做个了解。

CGLib实现的动态代理

CGLib动态代理的全称为 Code Generation Library,它是一个强大的高性能的,高质量的代码生成类库,就可以在运行期扩展Java类与实现Java接口,CGLib它封装了asm,可以再运行期动态生成新的class。CGLIB和JDK动态代理相比较的话:JDK创建的代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则就可以通过CGLib来创建动态代理了。

JDK 对接口创建代理实例,CGLIB 可以对类创建代理实例。

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值