java 动态代理模式

一.相关类及其方法:
java.lang.reflect.Proxy,
Proxy
提供用于创建动态代理类和实例的静态方法.
newProxyInstance()
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
(详见api文档)

java.lang.reflect.InvocationHandler,
InvocationHandler
是代理实例的调用处理程序
实现的接口。
invoke()
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
(详见api文档)
二.源代码:
被代理对象的接口及实现类:
 
package
com.ml.test;
 
public interface Manager {
public void
modify();
}
 
package com.ml.test;
 
public class
ManagerImpl implements Manager {
 
@Override
public void modify()
{
   System.out.println("*******modify()方法被调用");
}
}
业务代理类:
package
com.ml.test;
 
import java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
 
public class BusinessHandler implements
InvocationHandler {
 
private Object object =
null;
 
public BusinessHandler(Object object) {
   this.object =
object;
}
 
@Override
public Object invoke(Object proxy, Method
method, Object[] args)
    throws Throwable
{
   System.out.println("do something
before method");
   Object ret =
method.invoke(this.object, args);
   System.out.println("do
something after method");
   return ret;
 
}
}

客户端类:
 
package
com.ml.test;
import java.lang.reflect.Proxy;
public class Client
{
 
public static void main(String[] args) {
   // 元对象(被代理对象)
   ManagerImpl managerImpl = new
ManagerImpl();
 
   // 业务代理类
   BusinessHandler
securityHandler = new
BusinessHandler(managerImpl);
 
   //
获得代理类($Proxy0 extends Proxy implements Manager)的实例.
   Manager
managerProxy = (Manager)
Proxy.newProxyInstance(managerImpl
     .getClass().getClassLoader(),
managerImpl.getClass()
     .getInterfaces(),
securityHandler);
 
   managerProxy.modify();
}
}
三.执行结果:
do
something before method
*******modify()方法被调用
do something after
method
四.机制分析:
Proxy.(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h)做了以下几件事.
(1)根据参数loader和interfaces调用方法
getProxyClass(loader,
interfaces)创建代理类$Proxy.
$Proxy0类实现了interfaces的接口,并继承了Proxy类.
(2)实例化$Proxy0并在构造方法中把BusinessHandler传过去,接着$Proxy0调用父类Proxy的构造器,为h赋值,如下:
class
Proxy{
   InvocationHandler
h=null;
   protected Proxy(InvocationHandler h)
{
    this.h =
h;
   }
   ...
}

下面是本例的$Proxy0类的源码(好不容易才把它提出来):
 
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import
java.lang.reflect.UndeclaredThrowableException;
 
public final class
$Proxy0 extends Proxy implements Manager {
 
private static Method
m1;
private static Method m0;
private static Method m3;
private static
Method m2;
 
static {
   try
{
    m1 =
Class.forName("java.lang.Object").getMethod("equals",
      new Class[] {
Class.forName("java.lang.Object") });
    m0
=
Class.forName("java.lang.Object").getMethod("hashCode",
      new
Class[0]);
    m3 =
Class.forName("com.ml.test.Manager").getMethod("modify",
      new
Class[0]);
    m2 =
Class.forName("java.lang.Object").getMethod("toString",
      new Class[0]);
   } catch (NoSuchMethodException
nosuchmethodexception) {
    throw
new NoSuchMethodError(nosuchmethodexception.getMessage());
   } catch (ClassNotFoundException
classnotfoundexception) {
    throw
new
NoClassDefFoundError(classnotfoundexception.getMessage());
   }
}
 
public
$Proxy0(InvocationHandler invocationhandler) {
   super(invocationhandler);
}
 
@Override
public
final boolean equals(Object obj) {
   try
{
    return
((Boolean) super.h.invoke(this, m1, new Object[] { obj
}))
      .booleanValue();
   } catch (Throwable throwable)
{
    throw
new UndeclaredThrowableException(throwable);
   }
}
 
@Override
public
final int hashCode() {
   try {
    return ((Integer)
super.h.invoke(this, m0, null)).intValue();
   }
catch (Throwable throwable) {
    throw
new UndeclaredThrowableException(throwable);
   }
}
 
public
final void modify() {
   try {
    super.h.invoke(this, m3,
null);
    return;
   }
catch (Error e) {
   } catch (Throwable throwable)
{
    throw
new UndeclaredThrowableException(throwable);
   }
}
 
@Override
public
final String toString() {
   try {
    return (String) super.h.invoke(this,
m2, null);
   }
catch (Throwable throwable) {
    throw
new UndeclaredThrowableException(throwable);
   }
}
}
接着把得到的$Proxy0实例强制转换成Manager.
当执行managerProxy.modify()方法时,就调用了$Proxy0类中的modify()方法.
在modify方法中,调用父类Proxy中的h的invoke()方法.
即InvocationHandler.invoke();
以上一段是原作者的原话,在此本人详细解说一下:
            
Manager
managerProxy = (Manager)
Proxy.newProxyInstance(managerImpl
     .getClass().getClassLoader(),
managerImpl.getClass()
     .getInterfaces(),
securityHandler);
 
此句中Proxy.newProxyInstance(..)方法执行时生成了$Proxy0的内存字节码文件并return出来赋给了
managerProxy,强制转化成了Manager接口,同时$Proxy0也实现了Manager接口中的所有方法,所以在
 managerProxy.modify();
时就是调用了$Proxy0中的一下代码段:
            
public
final void modify() {
   try {
    super.h.invoke(this, m3, null);
//该段则执行了InvocationHandler.invoke();  super.h既是InvocationHandler
    return;
   }
catch (Error e) {
   } catch (Throwable throwable)
{
    throw
new UndeclaredThrowableException(throwable);
   }
}
 这样动态代理机制就实现了。
 所以JAVA的动态代理的关键就在Proxy.newProxyInstance(..)方法执行时生成了$Proxy0的内存字节码以及JDK的反射机制!

作者“林清杨--技术博客”

java 动态代理模式,布布扣,bubuko.com

时间: 2024-10-11 05:26:59

java 动态代理模式的相关文章

Java动态代理模式

1.如何实现静态代理模式? 能够想到的方式起码有两种继承和聚合. 创建一个接口 package com.jyd.proxy; /** * 定义一个可以工作的接口,定义一系列操作方法 * @author hadoop * */ public interface Workable { void renting(); } 创建一个类继承这个接口 package com.jyd.proxy; import java.util.Random; /** * 定义一个中介人来实现可以工作的接口 * @auth

Java动态代理模式 -- 保护代理

意义 将接口的调用统一到一个函数里处理,然后再去具体实例调用相应的方法,充当一个分发器的作用 user -> handler -> method 字典 动态:指的是在程序运行时才创建代理类 代理:与被代理类具有相同的属性,也就是被代理类有run方法,它也有run方法 保护代理:限制接口类的某些方法给特定的对象使用 Proxy类:Java反射包自带,其中newProxyInstance可以返回接口实现类的实例 组成 1.接口 Person类:其中有name与score相关的方法 自己本人可以修改

Java静态代理与动态代理模式的实现

前言:    在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总没有时间见面,他也没办法.后来,房东想了一个办法,他找到了一个人代替自己和小王洽谈,房东本人不用出面,他只要把他的对房客的要求告诉他找的那个人,那个人和你商量就可以了,这样就可以完成租房这件事了.这种现实场景比比皆是,所呈现出来的其实就是代理模式的原型的一种.我们把焦点转向编程,你是否在编程中经常遇见这样一个问题,对于访问某个对象,我们希望给它的方法前加入一

Java设计模式—Proxy动态代理模式

代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代理模式 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性.Java 动态代理机制以巧妙的方式近乎完

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

Java设计模式-代理模式之动态代理(附源码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的区别就是:动态代理是在运行时刻动态的创建出代理类及其对象.上篇中的静态代理是在编译的时候就确定了代理类具体类型,如果有多个类需要代理,那么就得创建多个.还有一点,如果Subject中新增了一个方法,那么对应的实现接口的类中也要相应的实习该方法,不符合设计模式原则. 动态代理的做法:在运行时刻,可以动态创建出一个实现了多个接口的代理类.每个代理类的对象都会关联一个表示内部处理

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

Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代理是在编译的时候就确定了代理类详细类型.假设有多个类须要代理.那么就得创建多个. 另一点,假设Subject中新增了一个方法,那么相应的实现接口的类中也要相应的实现这些方法. 动态代理的做法:在执行时刻.能够动态创建出一个实现了多个接口的代理类.每一个代理类的对象都会关联一个表示内部处理逻辑的Inv

代理模式和java动态代理

代理模式的作用及使用场景 使用代理模式的根本目的在于:如何在不直接操作对象的情况下,对此对象进行访问? 常用的场合包括:1)延迟加载:2)在调用实际对象的方法前后加入某些业务逻辑(作用有点像spring的AOP) 类结构: JAVA动态代理 JAVA提供了动态代理类以供用户方便地实现代理模式 public interface Subject { public void doRequest(); } public class SubjectImpl implements Subject { pub

《Java知识应用》模式实现Java 动态代理

动态代理说明:将你提供的接口改造成和你这个类有关的代理对象. Java动态代理案例和原理:https://www.cnblogs.com/jssj/p/11771408.html 我们无法像JVM一样不需要生成Java文件直接生成字节码.我们模拟就通过手工生成java,然后编译成Class文件来实现. 模式案例: package demo.knowledgepoints.invocationhandler; public interface MyInvocationHandler { publi

java动态代理的实现

动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 友情提示:本文略有难度,读者需具备代理模式相关基础知识,. 通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的方法都被固定,这种代理被称之为静态代理(Static Proxy).那么有没有一种机制能够让系统在运行时动态创建代理类?答案就是本文将要介绍的动态代理(Dynamic Proxy).动态代理是一种较