深入理解Spring核心技术06---手动实现AOP上篇

很对地方都说,Spring是以IOC和AOP为内核的一个一站式的解决方案,也就是框架。前面几篇博客给大家详细的解释了Spring中IOC实现的原理以及是如何管理对象之间的依赖关系,并且通过相应的案例给大家手动实现了一个IOC容器。那么今天就来给大家讲解一下AOP的原理,并带着大家也来手动实现一个AOP。

这里先来回顾一下AOP,AOP的全称叫做Aspect Oriented Programming即面向切面编程,在前面的一篇博客中已经给大家简单的阐述了AOP的基本思想,今天,就带着大家来手动实现一个AOP。当然在这之前我们需要了解一下代理模式,在前面就给大家简单的介绍了设计模式。今天先来带着大家人是一种新的设计模式----代理模式。

什么是代理模式呢?所谓代理模式口语化的解释就是找一个类去完成另外一个类该完成的事,类似于咱们租房子或者找工作时碰到的中介。好吧,确实是不好理解,那么就先来看看下面的案例吧,咱们先来写一段程序,来演示一下动态代理。

打开eclipse,新建工程,如下图所示::

为了方便演示,我将代码写入到上次的工程之中。大家只需要看aop_demo包下的的就可以了。好了,我们先来定义dao层中的接口,新建一个UserDao接口 ,在该接口中定义四个基本的增删该查的方法,代码如下:

public interface UserDao {
	public void save();
	public void update();
	public void delete();
	public void find();
}

接下来编写该接口的实现类,代码如下:

package aop_demo.dao;

public class UserDaoImpl implements UserDao{

	@Override
	public void save() {
		// TODO Auto-generated method stub
		System.out.println("添加用户执行了---------");
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		System.out.println("更新用户执行了---------");

	}

	@Override
	public void delete() {
		// TODO Auto-generated method stub
		System.out.println("删除用户执行了---------");

	}

	@Override
	public void find() {
		// TODO Auto-generated method stub
		System.out.println("查询用户执行了---------");

	}

}

好了,dao层的工作我们已经做完了 ,前面和大家提到过,当我们与数据库间胡的时候需要开启事务和提交事务,为了解决大量的重复代码,可以将这些重复的代码抽取出来,而这种思想就是AOP思想即面向切面编程。这里我们就来模拟一下开启事务和提交事务,下面再service包下定义一个类Aspect,该类的代码如下:

package aop_demo.service;

//对方法增强的类
public class Aspect {
	public void before() {
		System.out.println("【**********开启事务**********");
	}
	
	public void after() {
		System.out.println("**********提交事务**********】");
	}
}

大家可以看到上述类中简单的模拟了一下事务。相当于横向抽取出来的重复代码。可能有点不好理解,来回忆一下AOP的作用,在Spring中,为了将那些与业务无关,却为业务模块所共同调用的逻辑代码封装起来,于是就提供了面向切面的支持,也称为SpringAOP 。好了,这里的两个方法就是模拟一下抽取出重复的代码。

来看下面一个类,下面这个类时本案例的核心,代码如下

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

import aop_demo.dao.UserDao;
import aop_demo.dao.UserDaoImpl;

/**
 * 
 * @author 灿灿
 *
 */
public class BeanFactory {
	public static UserDao getBean() {
		//准备目标类
		final UserDao userDao = new UserDaoImpl();
		//创建Aspect的对象
		final Aspect aspect = new Aspect();
		//使用代理类对目标对象进行增强
		return (UserDao)Proxy.newProxyInstance(BeanFactory.class.getClassLoader(),
				new Class[] {UserDao.class},new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// TODO Auto-generated method stub
						//前增强
						aspect.before();
						//目标方法
						Object object = method.invoke(userDao, args);
						//后增强
						aspect.after();
						return object;
					}
				});
		
		
	}
}

首先getBean方法相当于Spring中的IOC容器,用于提供一个对象,这里需要大家了解一下Proxy这个类,这里给出api文档中的解释,如下图所示:

从上图中我们知道Proxy类是用来实现动态代理的类,本案例中实现AOP就是依靠该技术实现的,大家可以看到上述代码中用到的就是 Proxy中的newProxyInstance方法来实现的,这里解释一下参数列表,第一个参数是代理类的类加载器,第二个参数是需要增强的字节码对象,即代理类要增强的目标接口,因为支持增强多个类,因此这里可以是一个字节码对象的数组,第三个参数是InvocationHandler对象,即需要增强的方法。该对象有需要接受三个参数,前两个参数是增强的方法,后一个是目标类的方法,即需要增强的类的方法,由于可以增强多个类因此可以试对象数组。好了,基本的工作差不多已经完成了。

下面的这个类就是测试类了,来看看我们手动实现的Aop的效果了。

public class AOP_Test {
	@Test
	public void userDao() {
		UserDao userDao = new UserDaoImpl();
		//执行方法
		userDao.save();
		userDao.delete();
		userDao.update();
		userDao.find();
	}
}
	

运行效果如下图所示:

可以看到,这是正常的方式去创建对象,调用对象的方法,并没有对方法进行增强,下面我们来试试使用动态代理技术对方法增强的效果,好了,在测试类中再定义一个测试方法,代码如下所示:

@Test
	public void testAop() {
		//获取UserDao对象
		UserDao userDao = BeanFactory.getBean();
		//执行方法
		userDao.save();
		userDao.delete();
		userDao.update();
		userDao.find();
	}

结果如下图所示:

大家可以看到每个方法都被增强了,好了这就是今天给大家手动实现的一个AOP小案例了,大家仔细观察这两个方法就可以发现,两个方法中仅仅就是获取对象的方式不同,这里这样写是有原因的,这里主要就是给大家模拟一下IOC容器,好了,希望大家好好的看一下这篇博客中的小案例,下一篇博客中给大家用另外一个方式实现AOP。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值