java中的动态代理

代理模式的目的:

在不改变代源码的情况下,实现对目标对象的功能的扩展

 

  • 生活中的原生的例子

假如现在有一个歌手,名字叫做Singer,这个对象有一个唱歌的方法sing()。

 public class Singer{
     public void sing(){
         System.out.println("唱一首歌");
     } 
 }

现在你通过某种方式创建了一个歌手的对象,在唱歌前想要对观众问好,唱歌后对观众进行答谢,即对目标对象Singer的sing方法功能进行扩展

 

 public void sing(){
     System.out.println("向观众问好");
     System.out.println("唱一首歌");
     System.out.println("谢谢大家");
 } 

 

 

  • 解决这个方法的第一个代理(静态代理)

这个代理是手动代理有几个类和一个功能接口组成

 

/**

*公用的一个功能接口

*/

interface ISinger{

void sing();//唱歌的方法

}

/**

*歌手对象实现功能接口(被代理对象)

*/

class Singer implements ISinger{

@Override

public void sing(){

System.out.println("我是一个歌手,我开始唱歌了");

}

}

 

/**

*代理类

*/

class SingerProxy implements ISinger{

//代理类必须持有代理对象的引用通过构造器注入

private Singer singer;

public Singer Proxy(Singersinger){

this.singer=singer;

}

//对方法进行扩展

@Override

public void sing(){

System.out.println("首先我需要向观众问好!");

singer.sing();

System.out.println("答谢观众!");

}

}

public class TestStaticProxy{

public static void main(String[]args){

//1.创建被代理对象

Singer singer = new Singer();

//2.创建代理类,并注入被代理的对象

SingerProxy singerProxy = new SingerProxy(singer);

//3.执行已经扩展的代理类的方法

singerProxy.sing();

}

}

 

 

很简单的就实现了一个静态的代理,歌手只用做自己的唱歌的功能,很好的实现了解耦,也实现了对功能的扩展,注意一点代理类必须持有被代理对象的引用

缺点:就是每一个代理类都需要自己动手写,当公用方法接口改变了之后就需要去手动的维护,维护起来比较麻烦。

 

 

  • 写一个动态的代理
    1. 简单的实现一个动态代理通过匿名内部类实现

public class TestDynamicProxy{

public static void main(String[] args){

Singer singer = new Singer();

ISingerproxy = (ISinger)Proxy.newProxyInstance(singer.getClass().getClassLoader(),singer.getClass().getInterfaces(),new InvocationHandler(){

@Override

public Object invoke(Object proxy,Method method,Object[] args)              throws Throwable{

System.out.println("向观众问好");

//执行目标对象方法

Object returnValue = method.invoke(singer,args);

System.out.println("谢谢大家");

return returnValue;

}

});

//调用代理对象的方法

proxy.sing();

}

}

这就实现了简单的动态代理,动态代理是所有Projxy.newProxyInstance()来获取一个动态的代理的实例然后调用目标方法就实现了动态的代理

 

  1. 动态代理实现的第二种

 

  1. 创建一个MyInvocationHandle类继承InvocationHandler这个接口,实现里面的invok方法
  2. 这个类持有被代理的对象
  3. 对invok的方法进行扩展

Public class MyInvocationHandle<T> implements InvocationHandler{

 

Private T tager;//被代理的实体类的引用

 

Public MyInvocationHandle(T tager){

this.tager=tager;

}

 

@Override

Public Object invoke(Object proxy,Method method,Object[] args)throwsThrowable{

//1.实现自己的扩展的方法

//2.直接目标方法,对象是代理对象tager

Objectinvoke=method.invoke(tager,args);

returninvoke;

}

}

 

  1. 测试这个动态代理

Public static void main(String[] args){

InvocationHandler ins = new MyInvocationHandle<Singer>(new Singer());

Object  singer  = Proxy.newProxyInstance(Singer.class.getClassLoader(),new Class[]{ISinger.class},ins);

((ISinger)singer).sing();

}

代理中首先创建一个自己的invocationHandler,然后传入自己的代理对象,然后把这对象给proxy来产生自己的代理对象其实第一种和第二种都是一种,只不过第二种来扩展方法的时候更方便

  • 解析动态代理的原理
    1. 动态代理主要是由两个方法,第一个是Proxy.newInstance方法、第二个是Proxy.getProxyClass方法
    2. Proxy.newInstance这个方法是获取一个代理的对象,参数是ClassLoder类加载器和代理的接口数组一般使用的是Object.class.getInterface()这个方法,然后再由一个是InvocationHandler这个实例,然后把InvocationHandler作为一个参数传入动态生成的类里面然后创建代理类
    3. Proxy.getProxyClass这个方法是在含在Proxy.newInstance里的面,当调用getProxyClass这个方法来创建一个代理类
    4. 创建好的代理类是存在jvm内存中的,写出来的结果展示位

public final class DynamicProxyExalpme extends Proxy implements ISinger{

        privatestaticMethodm1;

        privatestaticMethodm2;

        privatestaticMethodm3;

        privatestaticMethodm0;

        

        publicDynamicProxyExalpme(InvocationHandlervar1){

                super(var1);

        }

        

        static{

                try{

                        m1 =Class.forName("java.lang.Object").getMethod("equals",Class.forName("java.lang.Object"));

                        m2=Class.forName("java.lang.Object").getMethod("toString");

                        m3=Class.forName("proxy.ISinger").getMethod("sing");

                        m0=Class.forName("java.lang.Object").getMethod("hashCode");

                }catch(NoSuchMethodExceptionvar2){

                        thrownewNoSuchMethodError(var2.getMessage());

                }catch(ClassNotFoundExceptionvar3){

                        thrownewNoClassDefFoundError(var3.getMessage());

                }

        }

        Public final void sing(){

        try{

                super.h.invoke(this,m3,(Object[])null);

        }catch(RuntimeException|Errorvar2){

                throw var2;

        }catch(Throwablevar3){

                thrownewUndeclaredThrowableException(var3);

        }

        }

}

 

 

到了这个程度只是会用了,但是具体是如何实现的还是不太了解,等到自己的能力再高一点了自己来实现一个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值