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. Java中整数值的4中表示方式u

    Java中整数值有4中表示方式:十进制.二进制.八进制和十六进制,其中二进制的整数以0b或0B开头:八进制的整数以0开头: 十六进制的整数以0x或0X开头,其中10-15分别以a-f(此处的a-f不区 ...

  2. 痞子衡嵌入式:语音处理工具pzh-speech诞生记(4)- 音频录播实现(PyAudio)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是语音处理工具pzh-py-speech诞生之音频录播实现. 音频录播是pzh-py-speech的主要功能,pzh-py-speech借 ...

  3. 创建dynamics CRM client-side (十二) - HTML Web Resource

    HTML Web Resource是我们经常使用的一个功能. 第一步, 我们先创建好一个HTML. 接下来,我们要在web resource中创建新的html web resource. 我们在tex ...

  4. Java容器解析系列(12) LinkedHashMap 详解

    LinkedHashMap继承自HashMap,除了提供HashMap的功能外,LinkedHashMap还是维护一个双向链表(实际为带头结点的双向循环链表),持有所有的键值对的引用: 这个双向链表定 ...

  5. 19_05_01校内训练[polygon]

    题意 把一个边长为1的正n边形放到一个正m边形中,要求m边形完全覆盖n边形,可以有交点,并且中心重合.求正m边形的最小边长,至少精确到6位.要求logn计算. 思考 先考虑m|n的情况. 我们知道,正 ...

  6. ios--->泛型

    泛型 开发中使用场景: 1.限制集合中的类型,只能检测方法的调用,因为声明的泛型只能存在方法中 2.当一个类在声明的时候,某个对象的属性不确定,只有创建对象的时候才能确定,就可以使用泛型. 使用泛型的 ...

  7. 关于STM32串口接收中断中只能接收一个字节

    最近调试STM32的串口接收时发现例程中只能接收一个字节 例程如下: //初始化串口1 void uart_init(u32 bound){ //GPIO端口设置 GPIO_InitTypeDef G ...

  8. Spring注解开发系列Ⅳ --- 属性赋值

    在Spring框架中,属性的注入我们有多种方式,我们可以通过构造方法注入,可以通过set方法注入,也可以通过p名称空间注入,方式多种多样,对于复杂的数据类型比如对象.数组.List集合.map集合.P ...

  9. 【学习笔记】Linux基础(二):Linux的基本操作

    二.Linux的基本操作 0.正确的开关机操作 开机和登陆: 安全起见,一般不使用最高权限的root账户登入系统,光立系统时再使用 登录时为login程序提供账户名和密码即可,密码不会被显示,登陆后显 ...

  10. 【学习笔记】Linux基础(零):预备知识

    学习笔记(连载)之Linux系列 Note:本学习笔记源自<鸟哥的Linux私房菜(基础学习篇)>一书,为此书重要内容的摘要和总结,对于一些常识性的知识不再归纳 新型冠状病毒引发的肺炎战& ...