有时候需要在很多代码模块中引入一些公共的行为,例如日子,权限校验。如果在每个模块中都写,将引入很多重复的代码,耦合度太高,程序也不便于维护。运用一种称为AOP的技术可以实现公共行为的同时,也不会需要大量的维护成本,书写大量的代码。
AOP中文叫做面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP关注的方向是横向,不同于面向对象编程中关注的纵向。方式上有动态AOP和静态AOP。
AOP相关术语
Joinpoint 连接点 指那些被拦截到的点.在Spring中,这些点指方法(因为Spring只支持方法类型的连接点).
Pointcut 切入点 指需要(配置)被增强的Joinpoint.
Advice 通知/增强 指拦截到Joinpoint后要做的操作.通知分为前置通知/后置通知/异常通知/最终通知/环绕通知等.
Aspect 切面 切入点和通知的结合.
Target 目标对象 需要被代理(增强)的对象.
Proxy 代理对象 目标对象被AOP 织入 增强/通知后,产生的对象.
Weaving 织入 指把增强/通知应用到目标对象来创建代理对象的过程(Spring采用动态代理织入,AspectJ采用编译期织入和类装载期织入).
Introduction 引介 一种特殊通知,在不修改类代码的前提下,可以在运行期为类动态地添加一些Method/Field(不常用).
动态AOP
实现方式:
JDK动态代理:代理对象必须实现某个接口
cglib动态代理:通过在运行期生产目标对象的扩展子类
Spring中AOP实现方式:
1.经典的基于代理的AOP
2.使用AspectJ注解 通过
3.纯POJO切面 通过
4.注入式AspectJ切面
2,3两种AOP方式的配置,它们是一种自定义的标签,需要一套自定义的一套解析机制,注册的对应的解析器在AOPNamespaceHandler的init方法中。
public void init() {
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
aspectj-autoproxy对应的是AspectJAutoProxyBeanDefinitionParser,
config对应的是ConfigBeanDefinitionParser。在这两个类的解析方法中,都会对应创建
AbstractAutoProxyCreator子类的beanDefinition,AbstractAutoProxyCreator实现了BeanPostProcessor接口。在getbean的时候,会调用AbstractAutoProxyCreator的postProcessBeforeInstantiation方法。
静态AOP
静态AOP的实现主要通过在虚拟机启动时修改目标对象字节码的方式,完成对目标对象的能力增强,与动态代理相比效率更高,因为在动态代理调用过程中,需要动态创建一个代理类并代理目标对象,而静态代理启动时便完成了字节码增强,当系统调用目标类与调用正常的类并无差别。
实现
通过javaagent