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



静态代理模式模拟实例

应用场景介绍:这里有一个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();
}
}

执行结果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="动态代理对象运行结果">

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

Hibernate与代理模式的更多相关文章

  1. Hibernate 延迟加载的代理模式 和 Spring AOP的代理模式

    Hibernate 延迟加载的代理模式 和 Spring AOP的代理模式 主题 概念 Hibernate 延迟加载的代理模式 Spring AOP的代理模式 区别和联系 静态代理和动态代理 概念 代 ...

  2. Java-马士兵动态代理模式

    Java-马士兵动态代理模式 模拟jdk的动态代理的实现原理, 这些东西没有必要写出来,写项目的时候一般用不上,主要是为了面试和理解原理: java动态代理有什么作用 作用非常大,在很多底层框架中都会 ...

  3. Java 设计模式之代理模式

    1.  定义:为其它对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 2.  类图:代理对象和被代理 ...

  4. Proxy 代理模式

    简介 代理模式是用一个简单的对象来代替一个复杂的或者创建耗时的对象. java.lang.reflect.Proxy RMI 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对 ...

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

    共性问题: 1. 服务器启动报错,什么原因? * jar包缺少.jar包冲突 1) 先检查项目中是否缺少jar包引用 2) 服务器: 检查jar包有没有发布到服务器下:                 ...

  6. JAVA设计模式:代理模式&& 装饰模式区别

    在前面学习了代理模式和装饰模式后,发现对两者之间有时候会混淆,因此对两者进行了区别和理解: 装饰模式你可以这样理解,就像糖一样,卖的时候商家大多要在外面包一层糖纸,其实原本还是糖. public in ...

  7. linkin大话设计模式--代理模式

    代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象的时候,客户端并不关心是否可以准确的得到这个对象,他只要一个能够提供该功能的对象而已,此时我们就可以返回该对象的代理.总而言之,客户端 ...

  8. 设计模式之代理模式(Proxy)(2)

    代理模式是为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用,其特征是代理类与委托类有同样的接口. ...

  9. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

随机推荐

  1. vue --- 解读vue的中webpack.base.config.js

    const path = require('path') const utils = require('./utils')// 引入utils工具模块,具体查看我的博客关于utils的解释,utils ...

  2. BZOJ 1231 状压DP

    思路: f[i][j] i表示集合的组成 j表示选最后一个数 f[i][j]表示能选的方案数 f[i|(1<< k)][k]+=f[i][j]; k不属于i j属于i且符合题意 最后Σf[ ...

  3. 针对CDP协议攻击分析及安全防护

    针对CDP协议攻击分析及安全防护 熟悉Cisco的朋友都知道CDP协议是思科公司独特的发现协议,在思科公司出产的所有路由器和交换机里面都能运行此协议,一台运行C D P的路由器或交换机能够得知与它直接 ...

  4. Kinect 开发 —— 用户交互设计的若干思考

    Metro 风格 windows 8 Kinect Hub 手势原型设计 悬停选择     翻页控制 关节点重叠的处理方法 将箭靶设置在画面的边缘,这样玩家持弓的角度与屏幕保持一个大约45度的锐角,这 ...

  5. 51Nod 迷宫问题(最短路+权值)(模板)

    你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数.还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间.游戏规定了 ...

  6. vue中computed与watch的异同

    一.computed 和 watch   都可以观察页面的数据变化.当处理页面的数据变化时,我们有时候很容易滥用watch. 而通常更好的办法是使用computed属性,而不是命令是的watch回调. ...

  7. 【Uva 1632】Alibaba

    [Link]: [Description] 直线上有n(n≤10000)个点,其中第i个点的坐标是xi,且它会在di秒之后消失.Alibaba 可以从任意位置出发,求访问完所有点的最短时间.无解输出N ...

  8. hdu 1003 Max Sum 最大字段和 dp

    今天看了一上午dp.看不太懂啊.dp确实不简单.今天開始学习dp,搜了杭电的dp46道,慢慢来吧.白书上的写的 又不太具体,先写几道题目再说. .. 题目连接:id=516&page=1&qu ...

  9. BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)

    Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...

  10. http压测工具wrk

    安装 wrk支持大多数类UNIX系统,不支持windows.需要操作系统支持LuaJIT和OpenSSL,不过不用担心,大多数类Unix系统都支持.安装wrk非常简单,只要从github上下载wrk源 ...