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,Class<?>interfaces,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的类。打印结果如下:

开启事务..

执行了用户新增.....

提交事务....

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

源码下载

时间: 2024-10-07 16:12:12

springMVC学习(代理模式)的相关文章

设计模式学习——代理模式(Proxy Pattern)之 强制代理(强校验,防绕过)

上周温习了代理模式:http://www.cnblogs.com/chinxi/p/7354779.html 在此进行拓展,学习强制代理.但是发现网上大多例子都有个"天坑"(我是这么认为的),在得到代理类之后,真实对象也可以使用自己的方法,绕过了代理,这样使得代理没有了意义. 关于强制代理,字面上意思很清晰,即: 1.只能通过真实对象获取代理类来访问方法 2.其他方法比如直接new 一个代理类 访问方法(不通过本体获取),或是自己通过本体直接调用,都不行 网络上搜到的例子大多是这样的:

JAVA设计模式学习--代理模式

学习还是先从定义开始,反复的琢磨对模式的定义会让自己更深刻的记住. 代理模式定义:在某些场景下,系统中的目标对象不能被直接引用或者不适合直接引用,这时需要一个代理,起中介的作用以达到控制和增强目标对象. 代理模式分类:静态代理.动态代理. 代理模式结构: 1.抽象主题 2.真实主题 3.代理对象 上代码 静态代理 //抽象主题 public interface Target { public void display(); } //真实主题 public class RealTarget imp

java设计模式学习 ----- 代理模式(Proxy)

代理模式(Proxy) 其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思.再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法.先来看看关系图: 根据上文的阐述,代理模式就比较容易的理解了,我们看下代码: public interface Sourceable { publ

设计模式学习——代理模式(Proxy Pattern)

放假啦~学生们要买车票回家了,有汽车票.火车票,等.但是,车站很远,又要考试,怎么办呢?找代理买啊,虽然要多花点钱,但是,说不定在搞活动,有折扣呢~ 1 /// 2 /// @file Selling_Tickets.h 3 /// @author marrs([email protected]) 4 /// @date 2017-08-13 20:35:28 5 /// 6 7 #ifndef __SELLING_TICKETS_H__ 8 #define __SELLING_TICKETS_

设计模式学习之代理模式学习(一)

关于设计模式想必学习过Java语言的人都知道吧,当时对其进行深入学习的的人应该不是很多.在我看来设计方面的知识相比于框架应用配置等知识要有意思的多,并且设计模式的对一个程序员的编程思想提升有着很大的帮助.但是设计模式有二十三种,想要全部掌握还是要花点时间的,但如果是只学习常用的几种设计模式还是相对容易的.下面是我学习代理模式的一些心得. 问题引出      什么是代理模式,为什么要用代理模式. 现在有一个场景模拟:有一个tank类,他实现了Moveable接口,Moveable接口中有一个mov

重温设计模式(一)—代理模式

通过这次设计模式的交流,发现无论是技术上还是思想上需要提升的空间还有很多.收获比预期的要多的多.给我触动最深的就是以下几点: 1. 面向对象的精华:抽象.封装.继承.多态 2.设计模式六大原则的运用:单一职责.开闭原则.合成聚合.依赖倒装.里氏代换.迪米特 3.让自己思绪飞翔-大胆的去想象,只有去想了.做了,你才知道最后的结果 初次学习代理模式的博文:http://blog.csdn.net/gxq741718618/article/details/8781099 下面用另外一种愉快的心情了解一

第七话-代理模式

 谈恋爱啊谈恋爱.可是怎么追女神呢?你是否也试过代理模式呢?啊,什么?追女神还和模式有关?当然,让我一起学习代理模式. 一.什么是代理模式? 代理模式就是为其他对象提供一种代理以控制对这个对象的访问.有点拗口.其实就是中间人而已,A与B认识,B与C认识,A不认识C,那么A怎么追C呢?B呗. 二.代码实例(追女神) Main.java public class Main { public static void main(String[] args){ Nvshen nvshen = new

java/android 设计模式学习笔记(9)---代理模式

这篇博客我们来介绍一下代理模式(Proxy Pattern),代理模式也成为委托模式,是一个非常重要的设计模式,不少设计模式也都会有代理模式的影子.代理在我们日常生活中也很常见,比如上网时连接的代理服务器地址,更比如我们平时租房子,将找房子的过程代理给中介等等,都是代理模式在日常生活中的使用例子. 代理模式中的代理对象能够连接任何事物:一个网络连接,一个占用很多内存的大对象,一个文件,或者是一些复制起来代价很高甚至根本不可能复制的一些资源.总之,代理是一个由客户端调用去访问幕后真正服务的包装对象

java代理模式学习

Java动态代理模式 1. 代理:一个角色代表别一个角色来完成某些特定的功能. 比如:生产商,中间商,客户这三者这间的关系 客户买产品并不直接与生产商打交道,也不用知道产品是如何产生的,客户只与中间商打交道,而中间商就可以对产品进行一些包装,提供一些售后的服务. 代理模式有三个角色: 1. 抽象主题角色 2. 代理主题角色 3. 实际被代理角色 其它类通过访问代理主题角色来访问实际被代理角色. 2. 下面我们来个一个静态代理的实现. 我以一个坦克为例. 抽象主题角色:Moveable Java代