深入理解spring——AOP详解

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

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

将重复的代码抽取出来(不同的模块),在需要时统一调用,可以不同的模块按不同的顺序调用,解耦。

所有的Java程序的class都要通过相应的类加载器(Classloader)加载到Java虚拟机之后才可以运行。默认的类加载器会读取class字节码文件,然后按照class字节码规范,解析并加载这些class文件到虚拟机运行。如果我们能够在这个class文件加载到虚拟机运行期间,将横切逻辑织入到class文件的话,是不是就完成了AOP和OOP的融合呢?

AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理、缓存、对象池管理以及日志记录

advice:切面增强设计;pointcut:切入点

advisor(通知器):把advice和pointcut结合起来,可以定义应该使用哪个advice并在哪个pointcut使用。advisor中有advice和pointcut两个属性,pointcut使用单例模式(饿汉,static final)

连接点和切点什么区别呢?一个修饰词是“可以”,一个修饰词是“具体”。在我看来,切点规定了哪些方法将被切面增强,满足切点的限定条件都将得到增强。而连接点表示了满足切点扫描的方法的集合,这些方法可能有些满足切点的限定条件,有些不满足。

springAOP就是把切面(AdviceAdvisor)织入(Weaving)到满足切点(PointCut)限定条件的连接点(JoinPoint)的过程。

Spring AOP实现中,使用的核心技术是动态代理,而这种动态代理实际上是JDK的一个特性(Proxy模式,在Proxy的调用过程中,如果客户调用Proxy的request方法,先调用Proxy的前处理方法,再调用目标对象的request方法,再调用Proxy的后处理方法(通过反射、拦截器链等实现))

实现:

ProxyFactoryBean是AOP中最重要的一个类,在xml文件中配置,并放入IoC中(),对于ProxyFactoryBean把需要对target目标对象增加的增强处理都通过getObject()方法封装了(工厂模式)。以getObject方法作为入口,spring AOP调用AopProxyFactory作为AopProxy代理对象的生产工厂,由它来负责产生相应的AopProxy代理对象(默认使用JDK的Proxy,或CGLIB)。

在AopProxy代理的接口方法被调用执行时(调用原对象的方法即调用代理对象的方法),首先会触发对这些方法调用进行拦截,这些拦截对目标调用的功能增强提供了工作空间,拦截过程在JDK的proxy代理对象中是通过invoke方法来完成的。

在Spring AOP通过JDK的Proxy方法生成代理对象时,相关的拦截器(一个通知器链)已经配置到代理对象中了。

在InvocationHandler的invoke回调中,首先会根据配置来对拦截器是否与当前调用方法相匹配进行判断,如果匹配则相应的拦截器开始发挥作用。这个过程是一个遍历的过程,它会遍历AopProxy代理对象中设置的拦截器链中的所有拦截器。拦截器逐一被调用,在拦截器都调用完后,才对目标对象方法调用。

通知器advisor在xml中配置,放在IoC容器中,拦截器、通知器等一些信息是存放在AdvisorSupport类中,通过getBean获取。在ProxyFactoryBean中获取IoC容器是实现了BeanFactoryAware接口。

为了完成AOP应用需要的对目标对象增强,对于每种advice通知,spring设计了对应的AdviceAdapter通知适配器,这些通知适配器实现了advice通知对目标对象的不同增强方式(before、after等)。对于这些适配器,在AopProxy回调方法中有一个注册机制。完成注册后,拦截器链中运行的拦截器已经是经过适配的拦截器(实际上是通知器)了。

如果是适配器支持的adapter.supportsAdvice(advice)(advice根据配置文件有before、after等类型),就将生成的包装后的拦截器,放入拦截器链,如MethodBeforeAdviceAdapter,会产生MethodBeforeAdviceInterceptor,这个包装后的拦截器会先调用advice.before方法,在继续遍历拦截器链(methodInvocation.proceed())。如果是after类型,就先继续遍历拦截器链(methodInvocation.proceed()),再调用after方法。Throws是通过catch中捕获异常实现的。相当于拦截器链中有很多adapter包装后的拦截器,依次遍历每个拦截器,调用其方法,从而实现了增强

电源适配器,它是用于电流变换(整流)的设备。适配器的存在,就是为了将已存在的东西(接口)转换成适合我们的需要、能被我们所利用。

你可能感兴趣的:(深入理解spring,spring,java,后端)