Hibernate与代理模式

代理模式:当需要调用某个对象的时候,不需要关心拿到的是不是一定是这个对象,它需要的是,我拿到的这个对象能够完成我想要让它完成的任务即可,也就是说,这时调用方可以拿到一个代理的一个对象,这个对象可以调用它想创建的对象的方法完成调用方的任务就好了。

静态代理模式模拟实例

应用场景介绍:这里有一个PDF,我想打开,但是,初始化的过程比较耗时,那么在这个时候如果在创建对象的时候直接初始化那么势必会消耗掉一定的时间,但是并不一定初始化完成以后就直接要打开,可能过一段时间之后才需要打开呢,是有可能的。

File的一个接口,这个接口定义了一个openFile的方法。

package com.siti.proxytest1;

public interface File {

	/**
	 * 打开文件
	 */
	public void openFile();
}

PDFFile实现File接口,并实现openFile方法。

package com.siti.proxytest1;

public class PDFFile implements File{

	/**
	 * sleep一秒钟表示初始化的时候的耗时
	 */
	public PDFFile(){
		try {
			Thread.sleep(1000);
			System.out.println("PDF文件加载成功~");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void openFile() {
		System.out.println("PDF文件打开!");
	}

}

PDFFile的代理类,也要实现File接口,并实现openFile方法,在这个方法当中并不是从新的实现一遍PDFFile的openFile方法,而是将获得调用者想要创建的那个对象的实例,用这个实例去调用具体的实现方法。代码如下:

package com.siti.proxytest1;

public class PDFFileProxy implements File{

	private PDFFile pdfFile;
	/**
	 * 获取代理对象
	 * @param pdfFile
	 */
	public PDFFileProxy(PDFFile pdfFile){
		this.pdfFile = pdfFile;
	}
	/**
	 * 代理对象调用openFile方法时,才会创建pdfFile对象(耗时1s);
	 * 然后执行对象的openFile方法完成。
	 */
	@Override
	public void openFile() {
		if(pdfFile == null){
			this.pdfFile = new PDFFile();
		}
		pdfFile.openFile();
	}

}

在这个代理类中,可以清楚的看到,当创建一个代理对象传了null参数的时候,并没有直接得到pdfFile的实例,这时候速度非常快的创建完成了,当你调用执行的时候才会创建真正的实例,并调用该对象的方法,完成调用者的请求。测试代码如下:

package com.siti.proxytest1;

public class ProxyTest {

	public static void main(String[] args) {
		Long beginTime = System.currentTimeMillis();
		// 创建代理对象
		PDFFileProxy proxy = new PDFFileProxy(null);
		Long MiddTime = System.currentTimeMillis();

		System.out.println("创建代理对象耗时:" + (MiddTime - beginTime));

		// 调用openFile方法,创建实际的PDFFile对象并执行openFile方法
		// 如果此时不调用openFile的话那么这一秒钟的时间就会被节约下来,那么只是消耗了创建代理对象的时间(很少的时间)
		proxy.openFile();
		System.out.println("打开文件耗时:" + (System.currentTimeMillis() - beginTime));

	}
}

测试结果如下:

当然,系统的最终开销并没有减少,但是有的时候创建完对象之后并不一定就会直接调用它的方法,甚至直到被回收也没有调用,那么这时候代理模式很显然的效率更高,再者就是推迟了对象的创建时间,保障前面的程序运行流畅的,减少对象在内存中的存活时间,宏观上减少了内存的消耗。

Hibernate默认使用延迟加载(懒加载),也就是,当一个对象关联着另一个对象的时候,默认是不被直接加载的,它会获得一个代理对象,等到真正调用的时候,这个对象才真正的被创建。

动态代理模式模拟实例

借用上面类似的例子

首先还是一个File接口:

package com.siti.proxytest2;

public interface File {

	/**
	 * 加载文件
	 */
	public void loadFile();

	/**
	 * 打开文件
	 */
	public void openFile();

}

PDFFile对File接口进行实现:

package com.siti.proxytest2;

public class PDFFile implements File{

	@Override
	public void openFile() {
		System.out.println("PDF文件打开!");
	}

	@Override
	public void loadFile() {
		System.out.println("PDF文件加载成功~");
	}

}

创建一个事务类,表示事务机制。

package com.siti.proxytest2;

public class TransactionManager {

	/**
	 * 事务开启
	 */
	public void transactionStart(){
		System.out.println("事务开启!");
	}

	/**
	 * 事务关闭
	 */
	public void transactionEnd(){
		System.out.println("事务关闭!");
	}
}

接下来是MyInvocationHandler类实现InvocationHandler,实现的invoke方法将作为代理对象的方法实现。

package com.siti.proxytest2;

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

public class MyInvocationHandler implements InvocationHandler {

	// 需要被代理的对象
	private Object targetObj;

	public void setProxyObj(Object targetObj){
		this.targetObj = targetObj;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		TransactionManager transaction = new TransactionManager();
		transaction.transactionStart();
		// 执行targetObj的method方法
		Object obj = method.invoke(targetObj, args);
		transaction.transactionEnd();
		return obj;
	}

}

上面的invoke方法将会作为动态代理对象的所有方法的真正实现者。这样的话即调用了需要调用的方法又增加了一层事务管理机制。

package com.siti.proxytest2;

import java.lang.reflect.Proxy;

public class ProxyFactory {

	public static Object getProxy(Object targetObj) {
		// 创建一个MyInvocationHandler
		MyInvocationHandler handler = new MyInvocationHandler();
		// 为MyInvocationHandler设置target对象
		handler.setProxyObj(targetObj);
		// 返回一个动态代理对象
		return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(),
				targetObj.getClass().getInterfaces(), handler);
	}
}

该类提供了一个getProxy()方法,该方法为目标对象生成一个动态代理对象,该动态代理对象可以看做是需要的目标对象使用,真正调用的时候会执行MyInvocationHandler的invoke方法,执行事务调用方法完成操作。

测试类如下:

package com.siti.proxytest2;

import com.siti.proxytest2.PDFFile;

public class ProxyTest {

	public static void main(String[] args) {
		File pdfFileTarget = new PDFFile();
		// 创建动态代理
		File pdfFile = (File) ProxyFactory.getProxy(pdfFileTarget);
		pdfFile.loadFile();
		pdfFile.openFile();
	}
}

运行结果:

动态代理可以灵活地实现解耦,这种方式可以为对象提供附加的功能。

时间: 2024-08-08 01:26:19

Hibernate与代理模式的相关文章

"围观"设计模式(12)--结构型之代理模式(Proxy Pattern)

维基百科 代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式. 所谓的代理者是指一个类可以作为其它东西的接口.代理者可以作任何东西的接口:网络连接.内存中的大对象.文件或其它昂贵或无法复制的资源.----WIKIPEDIA 个人理解 代理模式就是找另外的一个对象作为代理去为你实施请求,代理模式分为两种,一种是静态代理模式,另外一种是动态代理模式,静态代理模式是代理类为其创建一个对象,将需要代理的类的对象赋予代理类中的该对象,让代理类中该对象去代替需要代理的类的对象去执行一定的

Spring框架_代理模式(静态代理,动态代理,cglib代理)

共性问题: 1. 服务器启动报错,什么原因? * jar包缺少.jar包冲突 1) 先检查项目中是否缺少jar包引用 2) 服务器: 检查jar包有没有发布到服务器下:                                      用户库jar包,需要手动发布到tomcat. (每次新建项目) 3) 重新发布项目 * 配置文件错误 (web.xml / struts.xml /bean.xml /hibernate.xml / *.hbm.xml) 明确的提示 * 端口占用 * we

【大话设计模式】——代理模式

对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念.Hibernate 的继承映射可以理解持久化类之间的继承关系.例如:人和学生之间的关系.学生继承了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到. Hibernate支持三种继承映射策略: 使用 subclass 进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态. 使用 joined-subclass 进行映射: 对于继承关系中的子类使用同一个表

从java 反射看延迟加载(代理模式)(二)

代理模式 代理模式使用代理对象完成用户请求,屏蔽用户对真实对象的访问.现实世界的代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的角度看,似乎当事人并不存在,因为他只和代理人通信.而事实上代理人是要有当事人的授权,并且在核心问题上还需要请示当事人. 在软件设计中,使用代理模式的意图也很多,比如因为安全原因需要屏蔽客户端直接访问真实对象,或者在远程调用中需要使用代理类处理远程方法调用的技术细节 (如 RMI),也可能为了提升系统性能,对真实对象进行封装,从而达到延迟加载的目的. 代理模式

(4)代理模式

1.概述 代理(Proxy)是一种设计模式, 提供了对目标对象(target)另外的访问方式:即通过代理(proxy)访问目标对象(target). 这样的好处: 可以在目标对象(target)实现的基础上,增强额外的功能操作.(扩展目标对象的功能). 举例:明星<---经纪人<-------用户 代理模式的关键点: 代理对象与目标对象. 2.静态代理 静态代理要求:代理对象(proxy)要实现与目标对象(target)一样的接口. IUserDao.java package com.rk.h

代理模式(静态代理)的通俗理解

代理模式分为两种:静态代理和动态代理. 首先不谈模式,举一个例子: 有一队很美丽的妹子,她们都是训练有素的迎宾小姐.平时忙于训练再加上人脉与广告投入不多,生意并不好.于是她们的老大提议去找一个礼仪公司合作,请他们把迎宾的活儿包给她们来做.恰好在某个公司有个接待外宾的活动,该活动交给一个这个知名的礼仪公司负责,礼仪公司就通知了迎宾小姐.在外宾下车时就要乐队奏乐,走到公司门口时,迎宾小姐需要致以问候.现在来模拟一下这个情景. //相当于迎宾小姐(委托类) public class HelloWorl

代理模式详解

什么是代理模式 代理模式是对象的结构模式.代理模式为其他对象提供一种代理以控制对这个对象的访问. 简单来说,在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 举个例子 我们打算结婚,但是婚礼的细节我们不想管,这时候我们找到婚庆公司,让他们帮我们包揽婚礼的细节,这就是"代理模式".既然是代理模式,那么就应该有一个代理角色和真实角色.例子中的"我们"就是真实角色,"婚庆公司"就是代理角色. 我

系统架构设计——设计模式之代理模式(二)CGLIB动态代理实现

像上一篇所说的代理模式其实是静态代理,在实际开发中其实应用不大,因为他需要事先知道被代理对象是谁,而且被代理对象和代理对象实现了公共的接口.实际情况往往并不能满足这些条件,我们往往在写代理模式的时候并不知道到时候被代理的对象是谁.解决办法就是--动态代理.以下我们将使用CGLIB实现动态代理. 一.动态代理概述 程序在运行期而不是编译器,生成被代理对象的代理对象,并且被代理对象并不需要和代理对象实现共同的接口.基于此,我们可以利用代理对象,提供一种以控制对被代理对象的访问. 1.1 动态代理的原

设计模式——代理模式与装饰器模式

代理模式 解决的问题:在直接访问对象时带来很大的开销.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层. 代理模式就相当于Windows 里面的快捷方式,它并不实现什么功能,而只是在中间加以控制:而装饰器模式为了增强功能. Java中的典型示例:静态代理:hibernate中的session.load()方法:动态代理:SpringAOP 代码