尚学堂百战程序员之AOP面向切面编程

尚学堂百战程序员之AOP面向切面编程
2018年05月30日 09:20 独一无二的楠竹

spring之AOP面向切面编程

AOP(Aspect Oriented Programming),面向切面编程,是面向对象编程OOP(Object Oriented Programming)的补充和完善。

OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应地对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理、和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

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

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

AOP的作用在于分离系统中的各种关注点,将核心关注点(核心业务逻辑)和横切关注点(增强逻辑)分离开来。应用了AOP之后,进行功能的扩展便不需要修改核心业务逻辑了。

应用场景:日志记录、性能统计、安全控制、事务处理、异常处理等等

主要意图:将日志记录、性能统计、安全控制、事务处理、异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非业务逻辑的方法中去,进而改变这些行为的时候不会影响到业务逻辑的代码。

AOP核心概念:

连接点(Joinpoint):表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,spring只支持方法执行连接点,其实在类中有很多的方法可以被增强,那么在实际操作中,定义要被增强的方法为切入点即可。

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

通知(Advice):所谓通知是指拦截到Joinpoint之后要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知、环绕通知

前置通知(Before Advice):在方法之前执行

后置通知(After Advice):在方法之后执行

环绕通知(Around Advice):在方法之前和之后执行

异常通知(After-Throwing Advice):方法出现异常执行

最终通知(After-Returning Advice):在返回之后执行

切面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。

引入(Introduction):引入是一种特殊的通知在不修改类代码的前提下,Introduction可以在允许期间为类动态地添加一些方法或属性

目标对象(Target Object):包含连接点的对象,也被称作被通知或被代理对象。

AOP代理(AOP Proxy):AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在spring中,AOP代理可以用JDK代理或CGLIB代理实现,而通过拦截器模型应用切面。

织入(Weaving):织入就是把一个advice应用到target的过程,是将切面增强逻辑应用到目标对象的连接点从而创建处AOP代理对象的过程。织入可以在编译期、类装载期、运行期进行。

spring AOP的底层实现

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

动态代理的方式

如果代理对象实现了接口,默认使用JDK动态代理来创建AOP代理,针对接口

如果代理对象没有实现接口,spring会切换使用CGLIB代理,针对类,当然spring AOP也可强制使用CGLIB

JDK动态代理实现:只能对实现了接口的类生成代理,而不是针对类,该目标类型实现的接口都将被代理,原理是通过在运行期间创建一个接口的实现类来完成对目标对象的代理,步骤如下

1.定义一个实现接口InvocationHandler的类

2.通过构造函数或者静态工厂方法等,注入被代理类

3.实现invoke(Object proxy,Method method,Object[]args)方法

4.在主函数中获得被代理类的类加载器

5.使用Proxy.newProxyInstance(classLoader,interfaces,args)产生一个代理对象

6.通过代理对象调用各种方法

CGLIB动态代理实现:针对类代理实现,对是否实现接口无要求,原理是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以被代理的类最好不要声明为final类型。

1.定义一个实现了MethodInterceptor接口的类

2.实现其intercept()方法,在其中调用proxy.invokeSuper()

静态代理和动态代理的区别

静态代理:自己编写代理类,然后在进行编译,在程序运行之前,代理类的.class文件就已经存在了

动态代理:在实现阶段不用关心代理谁,而在运行阶段(通过反射机制)才指定代理哪一个对象

后记:对于大部分转行的人来说,找机会把自己的基础知识补齐,边工作边补基础知识,真心很重要。

我们相信人人都可以成为一个IT大神,现在开始,选择一条阳光大道,助你入门,学习的路上不再迷茫。这里是北京尚学堂,初学者转行到IT行业的聚集地。"

财经自媒体联盟更多自媒体作者

新浪首页 语音播报 相关新闻 返回顶部