springMVC学习(代理模式)

            今天学习了,spring中的cglib代理实现,在正式开始学习cglib代理之前,我们先来学习自定义的代理,以及jdk为我们提供的代理模式。那么什么是代理模式,说的直白一点,就是用一个代理来实现我对具体对象的访问,或者操作,比如我们学习android开发的时候需要更新sdk,可是google的android开发官方网站是访问不到的(其实百度浏览器是可以的),这时候我们就需要了,而我们所用到的网络就可以称之为一个代理服务器,通过该代理,我们实现具体网站的访问,是不是很好理解呢。我们先来看看没有使用代理的例子:

       我们这个例子以添加用户举例:

首先我新建一个接口,用来定义添加用户操作的行为:

public interface UserDao {
	public void add();
}
然后新建一个实现类UserDaoImpl.java,在进行添加用户之前需要开启事物,添加完成之后,需要关闭事物。如下:

public class UserDaoImpl implements UserDao {

	@Override
	public void add() {
		System.out.println("开启事务.....");
		System.out.println("执行了用户新增.....");
		System.out.println("执提交事务.....");
	}
}
      可是这样的代码,耦合性很高,很难维护,比如:如果这个时候,我需要添加一个新注册的用户添加呢,这个时候就需要在新建一个UserRegDaoImpl然后实现UserDao接口,如果还有其他种类的用户新增的话,那么后果不堪设想啊。可以发现,利用传统的写法,没增加一个用户的种类,我们都需要新建一个该种类的实现类,然后实现UserDao接口,这样做代码就很难维护。接下来我们用代理类来实现这个需求:

public class UserDaoProxy implements UserDao {
	private UserDao target;//被代理目标  UserDaoImpl实例
	public UserDaoProxy(UserDao userDao){
		this.target=userDao;
	}
	
	public void add() {
		System.out.println("开启事务...");
		target.add();//System.out.println("执行了用户新增.....");
		System.out.println("提交事务...");
	}
}
       可以看到,此时我新建了一个UserDaoProxy的用户代理类。并且实现UserDao接口,此时我们并不需要关心具体添加的用户是什么类型的,我们需要做的就是为target属性设置需要被代理的用户类型即可,是不是很大程度降低了程序的耦合度。

此时运行改程序打印结果如下:

开启事务...
执行了用户新增.....
提交事务...
     

         下面来看看jdk中提供给我们代理是如何使用的,同样是新增用户的栗子:

         在jdk中为我们提供了一个Proxy类,该类有这样一个静态方法可以实现代理Proxy.newProxyInstance(ClassLoader classLoader,Classinterfaces,InvokecationHandler invokecationHandler);

这里有三个参数,非别代表如下意思:

classLoader:得到被代理类的类加载器

interfaces  :  得到被代理类实现实现的所有接口

invokecationHandler   该类用于回调被代理类中的方法

具体代码如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 前提:被代理目标必须实现接口
 * 生成的代理为接口的实现类	
 * @author Administrator
 *
 */
public class JDKProxy {
	private Object target;//被代理目标
	/**
	 * 动态生成指定的目标的代理对象
	 * @param objecet :被代理目标
	 * @return:代理
	 */
	public Object createProxy(Object object){
		target=object;
		/**
		 * loader - 定义代理类的类加载器
		   interfaces - 代理类要实现的接口列表
		    h - 指派方法调用的调用处理程序 
		 */
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new MyInvocationHandler());
	}
	
	class MyInvocationHandler implements InvocationHandler{
		/**
		 * proxy - 在其上调用方法的代理实例
		   method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
		   args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。
		 */
		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			System.out.println("开启事务...");
			Object returnValue = method.invoke(target, args);//回调被代理目标的方法userDaoImpl.add();
			System.out.println("提交事务");
			return returnValue;
		}
	}
	
	public static void main(String[] args) {
		JDKProxy jdkProxy = new JDKProxy();
		UserDao userDao = (UserDao)jdkProxy.createProxy(new UserDaoImpl());
		userDao.add();
	}
}
     代码中的注释比较详细,这里我就不详细解释了,需要注意一点:被代理的目标必须实现接口

   

     下面我们在利用spring为我们提供的jar包(cglib-nodep-2.1.jar),该jar中为我们提供了cglib代理的实现,同样是添加用户的例子:

package com.test.aop2;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
 * 前提: 要求被代理目标必须为非final的类(final修饰的类不能被继承)
 * 生成一个代理:被代理目标的子类
 * @author Administrator
 *
 */
public class CglibProxy {
	private Object target;
	
	public Object createProxy(Object object){
		this.target = object;
		Enhancer enhancer = new Enhancer();
		//设置父类(被代理目标)
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(new MyIntercetpor());
		return enhancer.create();//创建代理
	}
	/**
	 * 类似于jdk动态代理中MyInvocationHandler
	 * @author Administrator
	 *
	 */
	class MyIntercetpor implements MethodInterceptor{
		@Override
		public Object intercept(Object proxy, Method method, Object[] args,
				MethodProxy methodProxy) throws Throwable {
			System.out.println("开启事务..");
			Object returnValue = method.invoke(target, args);
			System.out.println("提交事务....");
			return returnValue;
		}
	}
	
	public static void main(String[] args) {
		CglibProxy cglibProxy = new CglibProxy();
		UserDao dao = (UserDaoImpl)cglibProxy.createProxy(new UserDaoImpl());
		dao.add();
	}
}
      同样,我们利用createProxy方法来生成代理,同样需要注意一点:被代理目标必须为非final的类。打印结果如下:

开启事务..
执行了用户新增.....
提交事务....

       好了,三种不同方法实现代理,就到这里了。

源码下载







你可能感兴趣的:(spring,springMVC学习)