IDB

package com.bjpowernode.proxy;

/**
* 代理类和目标类都必须使用同一个接口。
*/
public interface IDB { int insert();
int delete();
int update();
}

OracleDB

package com.bjpowernode.proxy;

/**
* 这是一个Oracle数据库相关的操作类
*
* 目标类(委托类)。
*/
public class OracleDB implements IDB{
public int insert(){ //以下是一个插入操作
System.out.println("Oracle insert data....");
try {
Thread.sleep(526);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
} public int delete(){ //以下是一个删除操作
System.out.println("Oracle delete data....");
try {
Thread.sleep(569);
} catch (InterruptedException e) {
e.printStackTrace();
} return 0;
} public int update(){ //以下是一个更新操作
System.out.println("Oracle update data....");
try {
Thread.sleep(456);
} catch (InterruptedException e) {
e.printStackTrace();
} return 0;
} }

TimeInvocationHandler

package com.bjpowernode.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; /**
* 注册在这个接口中的代码,在代理对象调用代理方法的时候,自动执行。
* 我们的扩展代码就注册在这个类中。
*/
public class TimeInvocationHandler implements InvocationHandler { //这个程序运行期,obj引用中保存了内存地址指向的对象是一个目标对象。
private Object obj; public TimeInvocationHandler(Object obj){
this.obj = obj;
} /**
* proxy 是代理对象的引用。
* method 是目标类中的目标方法
* args 是目标类中的目标方法的实参
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable { long begin = System.currentTimeMillis(); //通过反射机制去调用目标类中的目标方法
Object retValue = method.invoke(obj, args); long end = System.currentTimeMillis();
System.out.println("方法执行所耗费" + (end-begin) + "毫秒"); return retValue;
} }

Test

package com.bjpowernode.proxy;

import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {

        //创建目标类对象
IDB db = new OracleDB(); //创建代理对象
//DBProxy dbProxy = new DBProxy(); //这是静态代理模式中创建对象,因为DBProxy是我们程序员手动编写的。 //创建代理对象(这次创建代理对象是交给JVM完成,包括在这个过程中,JVM也会自动生成“代理类的字节码”)
//这个代理类是动态生成的字节码不会以.class文件的形式保存在硬盘上,所以我们称作动态代理。 //第一个参数是类装载器:JVM会在内存中自动生成一个字节码,但是这个字节码要想运行,必须经过类装载器的装载
//然后进一步解析,所以必须传递一个类装载器,这个类装载器就是用来装载这个临时的“字节码”。
//代理类和目标类必须使用同一个类装载器。 //第二个参数:是JVM在生成代理类的时候需要实现接口,但是这个接口又不能随便写,因为代理类和目标类要求实现相同的接口。
//所以我们将目标类实现的接口获取到之后传递过来就行了。
//JDK中提供的代理模式只能代理接口。如果目标类它的父类型不是一个接口而是一个抽象类,那么JDK中提供的动态代理就不能用了,需要使用
//第三方组件,例如:cglib。 //第三个参数:是InvocationHandler,这是一个接口,这个接口中的方法会在代理类调用代理方法的时候自动执行。
IDB dbProxy = (IDB)Proxy.newProxyInstance(db.getClass().getClassLoader(), db.getClass().getInterfaces(), new TimeInvocationHandler(db)); //通过代理对象中的方法去执行目标对象中的方法。
dbProxy.insert(); //dbProxy是一个动态生成的代理对象,由于这个代理对象实现了和OracleDB一样的接口,所以可以用IDB接口指向JVM中的代理对象。
dbProxy.delete(); // 这里调用的delete方法是是代理类中的代理方法,不是目标类中的目标方法。但是一定会通过代理方法去调用目标方法。
dbProxy.update(); } }

  

代理模式-jdk动态代理的更多相关文章

  1. 动态代理模式——JDK动态代理

    今天,我就来讲一下动态代理的设计模式. 动态代理的意义在于生成一个代理对象,来代理真实对象,从而控制真实对象的访问.操作动态代理需要两个步骤:一.代理对象和真实对象建立代理关系.二.实现代理对象的代理 ...

  2. 静态代理与JDK动态代理

    demo地址: https://github.com/ZbLeaning/leaning 代理: 为其他对象提供一种代理以控制对这个对象的访问.分为静态代理和动态代理.代理模式的目的就是为真实业务对象 ...

  3. 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式

    从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...

  4. 代理模式详解:静态代理、JDK动态代理与Cglib动态代理

    代理模式简介分类 概念 ​ 代理,是为了在不修改目标对象的基础上,增强目标方法的业务逻辑. ​ 客户类需要执行的是目标对象的目标方法,但是真正执行的是代理对象的代理方法,客户类对目标对象的访问是通过代 ...

  5. Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

    一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法. ...

  6. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  7. (转)轻松学,Java 中的代理模式及动态代理

    背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...

  8. Java代理(静态代理、JDK动态代理、CGLIB动态代理)

    Java中代理有静态代理和动态代理.静态代理的代理关系在编译时就确定了,而动态代理的代理关系是在运行期确定的.静态代理实现简单,适合于代理类较少且确定的情况,而动态代理则给我们提供了更大的灵活性. J ...

  9. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

随机推荐

  1. Jenkins-k8s-helm-harbor-githab-mysql-nfs微服务发布平台实战

    基于 K8S 构建 Jenkins 微服务发布平台 实现汇总: 发布流程设计讲解 准备基础环境 K8s环境(部署Ingress Controller,CoreDNS,Calico/Flannel) 部 ...

  2. 为什么在留言处插入<script>alert(1)</script>不弹框

    对于新手来说,往往会在留言地方插入<script>alert(1)</script>来检测是否有存储xss,事实是基本上不会弹框的,为啥? 通过查看源码,可知道<> ...

  3. Qt Installer Framework翻译(7-3)

    控制脚本 对于每个安装程序,您可以指定一个控制脚本,用来与安装程序的部分UI或功能进行交互.控制脚本可以在向导中添加和删除页面,更改现有页面,进行附加检查以及通过模拟用户单击来与UI交互.例如,这允许 ...

  4. 第一章001-003课程介绍、计算机网络概述、Internet概述

    计算机网络概述 课程安排: 第一章:概述 第二章:物理层 第三章:数据链路层 第四章:网络层 第五章:运输层 第六章:应用层 第七章:网络安全 第八章:因特网上的音频/视频服务 第九章:无线网络 第十 ...

  5. redis--->事务和锁

    redis 的事务.锁.流水线 Redis与 mysql事务的对比 开启 mysql:start transaction redis:multi 语句:mysql:普通sql redis:普通命令 成 ...

  6. Maven debug异常:Source not found.

    异常 用Maven debug 时出现了Source not found.,在调试过程中尝试添加源码也没有效果 解决方案 先把当前正在运行中的项目停止 右键项目 -> Debug As -> ...

  7. win10下Java12环境变量设置

    jdk下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html 变量设置: 右键"我的电脑" ...

  8. C语言I作业1

    1 你对软件工程专业或计算机科学与技术专业了解是怎样的? 软件工程顾名思义就是工程化的方法生产软件的一门学科.涉及到程序设计语言,数据库,软件开发工具,系统平台,标准,设计模式等方面. 2 你了解c语 ...

  9. 源码级别gdb远程调试(实现OS简单内核)

    最近在学着编写一个操作系统的简单内核,需要debug工具,我们这里使用gdb来进行调试,由于虚拟机运行和本机是两个部分,所以使用 gdb 的远程调试技术,这里对 gdb 常见调试以及远程调试方式做一个 ...

  10. docker nginx 实现图片预览

    一.实现 nginx http图片预览 1.创建本地配置文件目录以及配置文件 两种方式: 1.1.docker nginx将配置文件抽离到了/etc/nginx/conf.d,只需要配置default ...