简单描述Sping的AOP就是动态代理加拦截器链实现面向切面编程。当然AOP肯定没有这么简单,但是如果能自己实现AOP然后再去看源码的话是不是会更轻松点呢。
众所周知,Sping中AOP之所以能起作用就是我们在目标类的基础上定义了很多通知,例如before(前置通知),after-returning(后置通知),after(最终通知),after-throwing(异常通知),around(后置通知)等,那么我们就可以先从这里入手定义自己的通知
public interface FilterChain { /** * 目标方法执行之前执行 * * @timestamp Feb 17, 2016 2:41:59 PM */ public void before(Object target, Matcher[] matchers); /** * 目标方法执行之后执行 * * @timestamp Feb 17, 2016 2:42:12 PM */ public void after(Object target, Matcher[] matchers); }
target是目标类,matchers是匹配规则,它是个Matcher数组。之后可以再定义它的子接口扩展一下通知的功能
public interface FilterChainSub extends FilterChain { /** * 处理catch中的异常 * * @timestamp Feb 17, 2016 5:57:09 PM * @param exception * @param target */ public void operateException(Exception exception, Object target); /** * 释放资源,相当于finally中的逻辑 * * @timestamp Feb 17, 2016 4:25:53 PM * @param target */ public void destroy(Object target); }
现在通知定义好了,下一步就要决定是什么机制调用了实现这些接口的实体。
ApplicationFilterChain.java 由于这个源码比较多就不贴了,把链接放这了。下面来看一下这个类的主要字段
/** * 实现过滤器链 */ private List<FilterChain> filterChainList = new ArrayList<>(); /** * 索引计数器 */ private int index = 0; /** * 目标方法 */ private Method method = null; /** * 目标对象 */ private Object target = null; /** * 参数 */ private Object[] args = null; /** * 匹配规则 */ private Matcher[] matchers;
这个其实就是一个过滤器链,在Spring中是拦截器链。拦截器与过滤器的最主要的区别就是拦截器是动态代理实现的,而过滤器是函数的回调实现的。所以总感觉这里Filter好一些。也许设计AOP的大牛们是从整体上来看的,他就是一个Interceptor。不管什么了能实现功能再说。filterChainList是之后要添加的通知集合。下面来看一下核心代码
public Object invoke(ApplicationFilterChain chain) { if (filterChainList.size() < 0) return null; if (chain.size() == chain.index()) { Object obj = null; try { obj = method.invoke(target, args); } catch (Exception e) { throw new RuntimeException(e); } return obj; } // 获取过滤链中当前索引所指向的节点 FilterChain f = chain.get(chain.index); Object obj = null; f.before(target, matchers); // 过滤链中当前索引+1 this.index++; obj = invoke(this); f.after(target, matchers); return obj; }
外界要调用这个invoke方法就要传进来一个ApplicationFilterChain实例,如果传入的这个chain中通知集合元素的个数等于它的index的话就执行目标方法。否则就根据索引从链中获取通知然后执行前置通知,执行this.index++;重新调用invoke方法,再调用后置通知。这里为什么可以成this.index++不是chain吗?是因为我在外面调invoke的对象和传入的参数是一个对象,所以chain和this就是一个对象。使用哪个都可以,如果感觉别扭的话可以把this换成chain。再者就是invoke方法的调用会形成一个递归,知道index==size时就会跳出递归。现在知道了通知是怎么被调用的。下一步就可以讨论整体结构是怎么形成的了。
public class Interceptor implements InvocationHandler { /** * 目标对象 */ private Object target = null; /** * 过滤器链 */ private ApplicationFilterChain filterChain = null; private String[] regular; /** * * @param target * 目标类 * @param filterChain * 过滤器链 * @param regular * 匹配规则 */ public Interceptor(Object target, ApplicationFilterChain filterChain, String... regular) { super(); this.target = target; this.filterChain = filterChain; this.regular = regular; } /** * 执行目标方法 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // 设置目标方法,目标类,参数 filterChain.setMethod(method); filterChain.setTarget(target); filterChain.setArgs(args); filterChain.setRegular(regular); return filterChain.invoke(filterChain); } catch (Exception e) { filterChain.operateException(e); } finally { filterChain.destroy(target); } return null; } }
这里我定义了一个拦截器类然后让它实现了InvocationHandler接口,如果不知道InvocationHandler是什么作用的话可以先看一下动态代理,这里就不说了。这个拦截器类有一个构造函数接收三个参数分别是被代理的目标类,过滤器链,匹配规则。之后在代理方法中分别对ApplicationFilterChain的必要参数进行了设置然后调用filterChain.invoke(filterChain);现在知道了上面的那个invoke是在哪被调用了,再者就是这个代理方法中的try,catch块也是很有必要的,在invoke抛出异常时,会被catch接住,然后调用filterChain的operateException。看一下这个方法。
public void operateException(Exception e) { for (FilterChain f : filterChainList) { if (f instanceof FilterChainSub) { ((FilterChainSub) f).operateException(e, target); } } }
它会在通知链中找到可以处理异常的通知然后处理掉他。这是一个很大的隐患,时间原因就不改了,有兴趣的朋友可以试着改改。例如可以使用FilterChain出错时的index作索引,取出通知实例然后调用它的处理异常的方法。destroy是同样的思路也有同样的毛病。下面是测试代码
public class TestAop { public static void main(String[] args) { ApplicationFilterChain chain = new ApplicationFilterChain(); chain.addChain(new Transactional()); ServiceImpl impl = new ServiceImpl(); Interceptor inte = new Interceptor(impl, chain, "^save*"); Service s = (Service) Proxy.newProxyInstance(// TestAop.class.getClassLoader(), // impl.getClass().getInterfaces(), // inte); s.save(); } }
源码地址:SpingAOP小实现
有兴趣的话也可以看一下这个小demo的具体应用场景:its智能交通系统。还有这个系统的反思。下一步SpingAOP源码走起!
相关推荐
NULL 博文链接:https://zhang-yingjie-qq-com.iteye.com/blog/319927
Spring框架中的AOP模块使用了动态代理来实现AOP概念。Spring AOP允许开发者定义切面,并在这些切面中指定拦截的方法。Spring AOP支持不同的代理策略,包括JDK动态代理和CGLIB代理。如果被代理的类没有实现接口,...
**Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...
### Spring AOP面向方面编程原理:AOP概念详解 #### 一、引言 随着软件系统的日益复杂,传统的面向对象编程(OOP)...对于希望深入了解Spring AOP原理与实践的读者来说,掌握以上概念将是开启面向方面编程之旅的第一步。
本文将深入探讨Spring AOP的实现原理,以及如何使用反射来实现动态代理模式。 首先,我们需要了解AOP的基本概念。AOP的核心思想是切面,它包含两个主要部分:切点(Pointcut)和通知(Advice)。切点定义了在程序...
Spring AOP 的底层实现技术 --- Jdk 动态代理原理 JDK 动态代理是 Spring AOP 的底层实现技术,允许开发者在运行期创建接口的代理实例。在 JDK 1.3 以后,JDK 动态代理技术提供了实现 AOP 的绝好底层技术。JDK 动态...
可以帮助我们更好地理解其工作原理,例如,可以查看`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.aspectj.autoproxy.AspectJProxyFactoryBean`、`org.springframework.aop....
在Spring框架中,AOP(面向切面编程)就是基于Java动态代理来完成的,用于实现横切关注点,如日志、事务管理等。这篇博客的文章链接虽然没有给出具体内容,但我们可以根据Java动态代理和Spring AOP的基本概念来深入...
本示例将简要介绍如何在Spring应用中实现AOP,通过实际的代码示例帮助理解其工作原理。 首先,我们要理解AOP的核心概念。AOP是一种编程范式,它允许开发者定义“切面”(Aspects),这些切面封装了特定的关注点,如...
6. **代理(Proxy)**:Spring AOP通过动态代理实现切面的织入。对于接口,使用JDK动态代理;对于非接口类,使用CGLIB动态代理。 Spring的IOC和AOP机制使得开发者能够更专注于业务逻辑,而不是繁琐的依赖管理和横切...
**Spring AOP 学习笔记及实现Demo** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架中的一个重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP的主要目的...
Spring AOP 实现原理详解之 AOP 切面的实现 Spring AOP 是基于 IOC 的 Bean 加载来实现的,本文主要介绍 Spring AOP 原理解析的切面实现过程。AOP 切面的实现是将切面类的所有切面方法根据使用的注解生成对应 ...
现在让我们深入探讨JDK动态代理和Spring AOP的原理。 首先,JDK动态代理基于Java的反射机制,通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,...
一、适合人群 1、具备一定Java编程基础,初级开发者 ...(需要知道原理的请看spring aop源码,此处不做赘述) 3、可在现有源码上快速进行功能扩展 4、spring boot,mybatis,druid,spring aop的使用
在深入理解 Spring AOP 的源码时,需要熟悉 Spring IoC 的工作原理,以及 AOP 相关的概念,如切点表达式、通知类型等。了解这些基础知识可以帮助我们更好地掌握 Spring AOP 的实现细节。在分析源码时,可以参考作者...
【Spring AOP 原理解析】 Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许开发者定义“切面”来封装系统中的交叉关注点,如日志、事务管理、安全性等,从而提高代码的可复用性和可维护性。在Spring ...
本学习笔记将深入探讨Spring AOP的核心概念、工作原理以及实际应用。 1. **核心概念** - **切面(Aspect)**:切面是关注点的模块化,包含业务逻辑之外的横切关注点,如日志、事务管理。 - **连接点(Join Point...
本实例将详细探讨如何通过注解(Annotation)来实现Spring AOP的方法拦截。 一、Spring AOP基础 Spring AOP是Spring框架的一部分,它提供了一种在运行时织入横切关注点(如日志、事务管理等)到目标对象的能力。AOP...
本篇文章将深入探讨如何使用Spring AOP实现性能监控器,并通过源码分析来理解其工作原理。 首先,我们要了解AOP的核心概念——切面(Aspect)、通知(Advice)、连接点(Join Point)、切入点(Pointcut)和织入...
XML配置是Spring AOP早期的主要实现方式,虽然现在有更简洁的注解式配置,但理解XML配置方式对于深入理解AOP原理仍然很有帮助。下面我们将详细探讨如何通过XML配置实现Spring AOP。 首先,我们需要在Spring配置文件...