Spring AOP原理

Spring中有两大核心的内容,IoC(控制反转)和AOP(面向切面编程),深入学习了Spring之后发现,这两者在Spring中的地位非常高,并且我认为想要学好Spring框架体系,必须从底层去理解和亲自测试IoC和AOP的原理。

IoC已经在笔者之前发布的文章中提及,今天要讲述的是AOP的实现原理。

AOP的概念
众所周知许多的编程语言都是面向对象的,如Java、C++,而如今 面向对象已经俨然成了我们编程的思想深入人心,但是现实中有一些内容并不是面向对象可以解决的,所以AOP所存在的意义也就展现了。
AOP可以拦截一些方法,然后把哥个对象组织成一个整体,如网站的交易记录需要记录日志,约定好了动态的流程之后那么就可以在交易前输出交易前的准备工作和打印日志,在完成交易的时候打印交易订单并且输入日志,同样,当这一笔交易发生异常时也能够回滚事物并且输出提示异常信息。
可能经过以上一番话你会想到拦截器,其实事实就是AOP的实现和拦截器有着密不可分的关系。
之前在学习这方面的知识的时候在书上看到了很不错的一个解释AOP运行流程的小游戏,它虽与真正的AOP有着一定的区别,但是大体上却能很好的体现AOP的实现流程。
游戏约定如下:
首先提供一个Interceptor接口:

public interface Interceptor {
	
	//执行对应操作之前的方法
	public void before(Object obj);
	
	//执行完毕对应操作之后的方法
	public void after(Object obj);
	
	//正确执行无误,执行该方法
	public void afterReturning(Object obj);
	
	//执行方法异常,执行该方法
	public void afterThrowing(Object obj);
}

顾名思义,这是一个拦截器接口,接下来是它的实现类:


public class UserInterceptor implements Interceptor{

	@Override
	public void before(Object obj) {
		// TODO Auto-generated method stub
		System.out.println("准备执行printMessage()方法-------");
	}

	@Override
	public void after(Object obj) {
		// TODO Auto-generated method stub
		System.out.println("执行完毕printMessage()方法-------");
	}

	@Override
	public void afterReturning(Object obj) {
		// TODO Auto-generated method stub
		System.out.println("无异常发生,正常返回-------------");
	}

	@Override
	public void afterThrowing(Object obj) {
		// TODO Auto-generated method stub
		System.out.println("执行printMessage()方法出错请检查---------");
	}

}

然后是POJO:

package test_01;

public class User {
	
	private int id;
	
	private String name;
	
	private String note;
	
	//构造方法
	public User(int id,String name,String note) {
		this.id = id;
		this.name = name;
		this.note = note;
	}
	
	//set和get方法
	public int getId() {
		return id;
	}
	
	public void setId(int id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getNote() {
		return note;
	}
	
	public void setNote(String note) {
		this.note = note;
	}
	
	
}

同样我们还需要Service接口和它的实现类:


public interface UserService {
	public void printMessage(User user);
}	

package test_01;

public class UserServiceImpl implements UserService{

	@Override
	public void printMessage(User user) {
		// TODO Auto-generated method stub
		System.out.println("id--------"+user.getId());
		System.out.println("name------"+user.getName());
		System.out.println("note------"+user.getNote());
	}

}

接下来是具体类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyBeanUtil implements InvocationHandler{
	//被代理对象
	private Object obj;
	//拦截器
	private Interceptor interceptor = null;
	
	public static Object getBean(Object obj,Interceptor interceptor) {
		ProxyBeanUtil _this = new ProxyBeanUtil();
		//保存被代理对象
		_this.obj = obj;
		//保存拦截器
		_this.interceptor = interceptor;
		//生成代理对象并绑定方法
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), _this);
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		Object retObj = null;
		//判断是否产生了异常
		boolean exceptionFlag = false;
		//执行先行方法
		interceptor.before(obj);
		
		try {
		//反射所有方法
			retObj = method.invoke(obj, args);
		}catch(Exception ex) {
			exceptionFlag = true;
		}finally {
			interceptor.after(obj);
		}
		
		if(exceptionFlag) {
			interceptor.afterThrowing(obj);
		}else {
			interceptor.afterReturning(obj);
		}
		return retObj;
	}
	
}

proxyBeanFactory:


public class ProxyBeanFactory {
	public static <T> T getBean(T obj,Interceptor interceptor) {
		return (T) ProxyBeanUtil.getBean(obj,interceptor);
	}
}	

当你尝试了解Spring AOP的时候我想你肯定了解过了动态代理模式,如果你已经知晓JDK动态代理,那么当你去看getBean方法时候肯定会发现什么有意思的事情,没错,其实AOP的实现和动态代理有着不可分割的联系。ProxyBeanFactory类中的getBean方法可以得到目标方法的代理对象,并通过反射来完成对象的传递。而上述“游戏”则是使用了JDK动态代理。
最后,我们需要编写一个测试类来让“游戏”开始,

package test_01;

public class Main {
	public static void main(String[] agrs) {
		UserService userService = new UserServiceImpl();
		Interceptor interceptor = new UserInterceptor();
		
		UserService proxy = ProxyBeanFactory.getBean(userService, interceptor);
		
		User user = new User(1,"小华","销售部部长");
		
		proxy.printMessage(user);
		
		System.out.println("-------------------测试该方法---------------------");
		
		user = null;
		
		proxy.printMessage(user);
	}
}

当测试类中的user不为空时,我们就能测试before,after,和afterReturning方法,既然是测试,我们就必须测试所有的方法,所以最后我们将user置空,测试afterThrowing方法测试结果如下:
| 在这里插入图片描述
通过控制台的输出信息,我们就能大致的了解AOP的运行流程,它并不好理解,我们可以通过打断点去一步一步验证它,不要怕麻烦,这是成为一个合格程序员的最低门槛。

Spring AOP(Aspect-Oriented Programming)是一种基于面向切面编程的技术,它通过将一个应用程序分解成许多独立的部分,从而提高了应用程序的模块化程度,同时也提高了代码的可重用性和可维护性。 Spring AOP 是在运行时对程序进行修改的,它不需要重新编译源代码,因此使得代码的维护和修改更加方便。Spring AOP 原理主要分为以下几个方面: 1. 切面(Aspect):切面是一个类,其中包含了一组相关的Advice和其他相关的代码,用于在目标对象的方法执行前、执行后或者抛出异常时执行相应的操作。 2. 连接点(Join point):连接点是指在应用程序的执行过程中,可以被切面拦截的点,比如方法调用、异常抛出、属性赋值等。 3. 通知(Advice):通知是指在连接点处执行的代码,有多种类型的通知,包括前置通知(Before advice)、后置通知(After advice)、返回通知(After returning advice)、异常通知(After throwing advice)和环绕通知(Around advice)。 4. 切入点(Pointcut):切入点是一个表达式,用于定义哪些连接点会被切面拦截。 5. 代理(Proxy):代理是指在目标对象和切面之间创建的对象,它可以拦截目标对象的方法调用,并在方法执行前后执行相应的通知。 Spring AOP 的实现机制主要是通过 JDK 动态代理或者 CGLIB 动态代理来实现的。当目标对象实现了接口时,Spring AOP 使用 JDK 动态代理,否则使用 CGLIB 动态代理。在 JDK 动态代理中,代理对象实现了与目标对象相同的接口,而在 CGLIB 动态代理中,代理对象是目标对象的子类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值