欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java JDK动态代理实现原理

程序员文章站 2024-03-14 19:58:41
...

一、设计模式----代理(Proxy)

1.代理的汉语解释:代人担任职务,受委托当事人进行某种活动。

2.在Java设计模式中,代理是指为其他对象提供一种代理以控制对这个对象的访问。

3.代理类为委托类预处理消息,过滤消息或转发消息,以及进行消息被委托类执行后的后续处理。

4.代理类并未真正的代替委托类去处理核心事务,只是在委托类自己处理前后,做了一些修饰工作,核心工作仍由委托类自己完成。

5.现实生活中的例子:相亲机构(代理类),相亲者(委托类),相亲者会委托相亲机构,提供自己的个人信息、要求,然后相亲机构会为相亲者寻找匹配者,最后见面相亲的核心工作还是有相亲者自己完成。

二、代理模式基本原理

Java JDK动态代理实现原理

Java JDK动态代理实现原理

图爿转载自;https://blog.csdn.net/jiankunking/article/details/52143504

        代理类和委托类实现相同的接口,所以对于访问者来说没有区别,访问者调用代理类的方法,代理类内部又调用委托类的方法。通过代理类这一中间组件,可以有效地控制直接对委托类的访问,隐藏和保护了委托对象,通过这种方式可以为不同的控制策略预留了空间,从设计上获得了更大的灵活性。

三、静态代理

以相亲(blinddate)为例:

1.定义一个接口

 interface Subject{
public void blindDate(String s);
}

2.定义委托类

class Person implements Subject{
public void blindDate(String s){
    System.out.println("i am blinddating with "+s);
     }
}

3.定义代理

class DatgingAgency implments Subject{
  private Subject target;//受代理者,委托者,代理类需要知道代理谁,代谁做事
  public DatgingAgency(Subject target){
  this.target=target;
  }

public String beforeBlindDate(String s){
  return s;//寻找匹配者
}
public void blindDate(String s){
String s=beforeBlindDate(String s);
 target.blindDate(s);//相亲由委托类自己来进行
 }
}

4.测试

public static void main(args[]){

Person p=new Person();
DatingAgency da=new DatingAgency(p);
da.blindDate("志林姐姐");
}
总结:静态代理,说白了就是代理类已经写死了,程序在运行期需要加载代理类时,将事先在本地编译(或者其他方式)好的class文件加载到JVM供虚拟机使用。静态代理需要开发者自己去实现。


四、动态代理

        动态代理,相对于静态代理,意思就显而易见了,就是代理类实例是由运行期生成的,在JVM中动态地生成class文件并创建代理类实例。

1、反射技术

动态代理运用了大量反射机制,首先简单看看反射的运用:

Java JDK动态代理实现原理

Java JDK动态代理实现原理

2.JDK动态代理实例

(1)定义接口

public interface HelloService{
   public void sayHello(String name);
}

(2)定义委托类,委托类是真正的执行者

public class HelloServiceImpl implements HelloService{
    public void sayHello(String name){
    System.out.println("hello"+name);
  }
}

(3)首先介绍Java中关于动态代理的两个主要接口和类;

java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。

// 最主要的方法:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象
// 第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
Object invoke(Object proxy, Method method, Object[] args)

定义一个实现了InvocationHandler接口的类,这个类须绑定目标对象(即委托类),并利用Proxy的静态方法返回动态代理类的实例

public class HelloServiceHandler implements InvocationHandler{
/*
真实被代理对象
*/
private Object target;
  /*
  绑定委托对象,并返回一个代理类
  */
  public Object bind(Object target){
    this.target=target;
    //获取代理对象
    return Proxy.newProxyInstance(target.getClass().getClassLoader,target.getClass().getInterfaces(),this);
  }

  /*
  Proxy 代理对象
  */
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
    Object result=null;
    //反射方法前调用
    System.out.println(“我准备说hello”);
    //执行方法,相当于执行HelloServiceImpl类的sayHello方法
    result=method.invoke(target,args);
    //反射后调用
    System.out.println(“我说了hello”);
    return result;
  } 
}

(4)测试类

public class HelloServiceMain{
  public static void main(String[] args){
    HelloServiceHandler helloHandler=new HelloServiceHandler ();
    HelloService helloProxy=(HelloService)helloHandler.bind(new HelloServiceImpl());
    helloProxy.sayHello(“志林姐姐”);
  }
}