面向切面编程(Aspect Oriented Program)
我们知道,面向对象的思想是一切皆对象,三大特性是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是解决了软件系统中角色划分的问题,使类可重用。
但是人们也发现,在分散代码的同时,也增加了代码的重复性。比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
为了解决这一问题,AOP应运而生。这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。有了AOP,我们就可以把散布在各处与业务无关的模块,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。
AOP其实只是OOP的补充,以另一种视角进解耦。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。
分离出核心关注点、横切关注点,将横切关注点织入核心关注点模块,优点:
- 降低系统耦合度
- 提高系统扩展性
- 提高组件复用性
AOP术语
连接点(Joinpoint):程序执行中一个精确执行点,例如一个方法调用,Spring中一般指一个方法。
切入点(Pointcut):连接点的集合,这些连接点确认何时触发通知,通常采用正则、通配符语法
通知(Advice):连接点所采用的动作,如权限、日志模块
SpringAOP中,通知可以分为前置通知(Before advice)、后置通知(After Returning advice)、异常通知(After throwing advice)、最终通知(After finally advice)、环绕通知(Around Advice)
- 切面(Aspect):切入点+通知结合,包含了横切逻辑的定义 即什么时候在什么地方做什么事情。
- 引入(Introduction):为对象引入附加的方法和属性
- 目标对象(Target Object):被通知的对象,真正的业务逻辑
- AOP代理(AOP Proxy):AOP框架创建的代理对象
- 织入(Weaving):将切面应用到目标对象创建代理对象的过程
AOP实现方式
AOP是通过动态代理实现,Spring默认采用JDK动态代理(JdkDynamicAopProxy ),也可以支持CGLIB(CglibAopProxy),Spring会通过DefaultAopProxyFactory自动在JDK和CGLib之间转换。
关于动态代理可以参考本人之前的日志:设计模式-代理模式
使用Spring AOP
要在Spring中使用AOP,需要在配置文件上加上注释@EnableAspectJAutoProxy
简单例子,当用户请求Controller时,打印出对应方法名以及参数信息:
Controller方法:
验证结果:
扩展
Spring AOP在Java开发中有着重要的地位,Spring多个组件都是基于AOP开发,运用十分广泛。比如Spring Security 安全框架、Spring Transcation 事务管理、Spring MVC 异常处理、Spring Cache 缓存管理等。