`

SpingAOP原理小实现

阅读更多

      简单描述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源码走起!

 

1
4
分享到:
评论

相关推荐

    spring aop实现原理

    NULL 博文链接:https://zhang-yingjie-qq-com.iteye.com/blog/319927

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    Spring框架中的AOP模块使用了动态代理来实现AOP概念。Spring AOP允许开发者定义切面,并在这些切面中指定拦截的方法。Spring AOP支持不同的代理策略,包括JDK动态代理和CGLIB代理。如果被代理的类没有实现接口,...

    Spring AOP实现机制

    **Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...

    Spring AOP面向方面编程原理:AOP概念

    ### Spring AOP面向方面编程原理:AOP概念详解 #### 一、引言 随着软件系统的日益复杂,传统的面向对象编程(OOP)...对于希望深入了解Spring AOP原理与实践的读者来说,掌握以上概念将是开启面向方面编程之旅的第一步。

    反射实现 AOP 动态代理模式(Spring AOP 的实现 原理) - Java 例子 -

    本文将深入探讨Spring AOP的实现原理,以及如何使用反射来实现动态代理模式。 首先,我们需要了解AOP的基本概念。AOP的核心思想是切面,它包含两个主要部分:切点(Pointcut)和通知(Advice)。切点定义了在程序...

    Spring Aop的底层实现技术 --- Jdk动态代理原理

    Spring AOP 的底层实现技术 --- Jdk 动态代理原理 JDK 动态代理是 Spring AOP 的底层实现技术,允许开发者在运行期创建接口的代理实例。在 JDK 1.3 以后,JDK 动态代理技术提供了实现 AOP 的绝好底层技术。JDK 动态...

    Spring AOP的底层实现技术

    可以帮助我们更好地理解其工作原理,例如,可以查看`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.aspectj.autoproxy.AspectJProxyFactoryBean`、`org.springframework.aop....

    Java动态代理(Spring Aop原理)

    在Spring框架中,AOP(面向切面编程)就是基于Java动态代理来完成的,用于实现横切关注点,如日志、事务管理等。这篇博客的文章链接虽然没有给出具体内容,但我们可以根据Java动态代理和Spring AOP的基本概念来深入...

    简单spring aop 例子

    本示例将简要介绍如何在Spring应用中实现AOP,通过实际的代码示例帮助理解其工作原理。 首先,我们要理解AOP的核心概念。AOP是一种编程范式,它允许开发者定义“切面”(Aspects),这些切面封装了特定的关注点,如...

    spring ioc和aop原理流程图(详细)

    6. **代理(Proxy)**:Spring AOP通过动态代理实现切面的织入。对于接口,使用JDK动态代理;对于非接口类,使用CGLIB动态代理。 Spring的IOC和AOP机制使得开发者能够更专注于业务逻辑,而不是繁琐的依赖管理和横切...

    SpringAop学习笔记以及实现Demo

    **Spring AOP 学习笔记及实现Demo** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架中的一个重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP的主要目的...

    Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现.doc

    Spring AOP 实现原理详解之 AOP 切面的实现 Spring AOP 是基于 IOC 的 Bean 加载来实现的,本文主要介绍 Spring AOP 原理解析的切面实现过程。AOP 切面的实现是将切面类的所有切面方法根据使用的注解生成对应 ...

    JDK动态代理 spring aop 的原理

    现在让我们深入探讨JDK动态代理和Spring AOP的原理。 首先,JDK动态代理基于Java的反射机制,通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,...

    spring aop 自定义注解保存操作日志到mysql数据库 源码

    一、适合人群 1、具备一定Java编程基础,初级开发者 ...(需要知道原理的请看spring aop源码,此处不做赘述) 3、可在现有源码上快速进行功能扩展 4、spring boot,mybatis,druid,spring aop的使用

    死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序.pdf

    在深入理解 Spring AOP 的源码时,需要熟悉 Spring IoC 的工作原理,以及 AOP 相关的概念,如切点表达式、通知类型等。了解这些基础知识可以帮助我们更好地掌握 Spring AOP 的实现细节。在分析源码时,可以参考作者...

    spring aop 原理解析

    【Spring AOP 原理解析】 Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许开发者定义“切面”来封装系统中的交叉关注点,如日志、事务管理、安全性等,从而提高代码的可复用性和可维护性。在Spring ...

    spring aop 学习笔记

    本学习笔记将深入探讨Spring AOP的核心概念、工作原理以及实际应用。 1. **核心概念** - **切面(Aspect)**:切面是关注点的模块化,包含业务逻辑之外的横切关注点,如日志、事务管理。 - **连接点(Join Point...

    spring aop实例annotation方法实现

    本实例将详细探讨如何通过注解(Annotation)来实现Spring AOP的方法拦截。 一、Spring AOP基础 Spring AOP是Spring框架的一部分,它提供了一种在运行时织入横切关注点(如日志、事务管理等)到目标对象的能力。AOP...

    Spring aop 性能监控器

    本篇文章将深入探讨如何使用Spring AOP实现性能监控器,并通过源码分析来理解其工作原理。 首先,我们要了解AOP的核心概念——切面(Aspect)、通知(Advice)、连接点(Join Point)、切入点(Pointcut)和织入...

    Spring AOP 的实现例子(基于XML配置实现)

    XML配置是Spring AOP早期的主要实现方式,虽然现在有更简洁的注解式配置,但理解XML配置方式对于深入理解AOP原理仍然很有帮助。下面我们将详细探讨如何通过XML配置实现Spring AOP。 首先,我们需要在Spring配置文件...

Global site tag (gtag.js) - Google Analytics