java静态代理和动态代理

本文详细介绍了Java中的代理模式,包括静态代理和动态代理。动态代理在运行时创建代理对象,解决了静态代理的一对一问题,遵循开闭原则。文中通过一个实例展示了如何实现动态代理,并探讨了其内部原理,包括`Proxy`类的使用和代理对象的字节码生成。此外,还提供了动态生成代理类字节码并保存为.class文件的方法。
摘要由CSDN通过智能技术生成

代理模式三大角色

抽象接口:声明了真实对象和代理对象的公共接口

代理对象:包含真实对象,用户访问的是代理对象,代理对象再访问真实对象

真实对象:提供真正的能力

静态代理的问题

静态代理一般是一对一的形式,如果要新增真实对象类型,那么需要修改代理对象,违反了设计模式中的开闭原则

动态代理

在运行时创建代理对象,新增真实对象,只需要设置真实对象,然后动态创建代理对象即可。

例子

public interface IFactory {
         void sale();
}



public class AFactory implements IFactory {
         @Override

         public void sale() {
                  System.out.println("生产玩具");
         }

}



public class BFactory implements IFactory {

         @Override

         public void sale() {

                   System.out.println("生产餐具");

         }

}



public class Company implements InvocationHandler {

   //真实对象

   private IFactory factory;


   public void setFactory(IFactory factory) {

      this.factory = factory;

   }

   //动态代理

   public Object getProxyInstance() {

      return Proxy.newProxyInstance(

         factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);

   }

   @Override

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

      return method.invoke(factory, args);

   }

}

使用

public static void main(String[] args) {

      AFactory aFactory = new AFactory();

      BFactory bFactory = new BFactory();



      Company company = new Company();

//    company.setFactory(aFactory);

      company.setFactory(bFactory);



      //创建一个动态代理对象

      IFactory factory = (IFactory) company.getProxyInstance();

      factory.sale();

}

动态代理原理

Proxy.newInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h),内部调用

getProxyClass0(loader,ints),动态创建一个Class对象,然后通过反射拿到Constructor,调用constructor.newInstance(h),传入的就是InvocationHandle对象。

         getProxyClass0,可以通过ProxyGenerator的generateProxyClass方法创建一个byte数组,我们可以通过反射创建出byte数组,然后写到文件中,然后使用jd-gui工具,查看该class字节码内容。

         代理对象会继承Proxy类,实现自定义接口,如:IFactory,构造方法中需要传入InvocationHandler对象,当我们调用sale()的时候,实际调用的是this.h.invoke(proxy, m3,null)。

生成代理对象的class文件

public static void generateClassFile(Class clazz,String proxyName) throws Exception {

    /*ProxyGenerator.generateProxyClass(

            proxyName, interfaces, accessFlags);*/



    Class proxyGeneratorClazz = Class.forName("java.lang.reflect.ProxyGenerator");

    Method generateProxyClassMethod= proxyGeneratorClazz.getDeclaredMethod(

        "generateProxyClass", String.class, Class[].class);

    generateProxyClassMethod.setAccessible(true);



    byte[] proxyClassFile = (byte[]) generateProxyClassMethod.invoke(

        null, proxyName, new Class[]{clazz});

    String paths = clazz.getResource(".").getPath();

    System.out.println(paths);

    FileOutputStream out = null;



    try {

        out = new FileOutputStream(paths+proxyName+".class");

        out.write(proxyClassFile);

        out.flush();

    } catch (Exception e) {

        e.printStackTrace();

    }finally {

        try {

            out.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}

        

代理对象class具体内容

import com.example.myapplication.proxy.IFactory;

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 IFactory {

  private static Method m1;

  

  private static Method m2;

  

  private static Method m3;

  

  private static Method m0;

  

  public $Proxy0(InvocationHandler paramInvocationHandler) {

    super(paramInvocationHandler);

  }

  

  public final boolean equals(Object paramObject) {

    try {

      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();

    } catch (Error|RuntimeException error) {

      throw null;

    } catch (Throwable throwable) {

      throw new UndeclaredThrowableException(throwable);

    } 

  }

  

  public final String toString() {

    try {

      return (String)this.h.invoke(this, m2, null);

    } catch (Error|RuntimeException error) {

      throw null;

    } catch (Throwable throwable) {

      throw new UndeclaredThrowableException(throwable);

    } 

  }

  

  public final void sale() {

    try {

      this.h.invoke(this, m3, null);

      return;

    } catch (Error|RuntimeException error) {

      throw null;

    } catch (Throwable throwable) {

      throw new UndeclaredThrowableException(throwable);

    } 

  }

  

  public final int hashCode() {

    try {

      return ((Integer)this.h.invoke(this, m0, null)).intValue();

    } catch (Error|RuntimeException error) {

      throw null;

    } catch (Throwable throwable) {

      throw new UndeclaredThrowableException(throwable);

    } 

  }

  

  static {

    try {

      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });

      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);

      m3 = Class.forName("com.example.myapplication.proxy.IFactory").getMethod("sale", new Class[0]);

      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);

      return;

    } catch (NoSuchMethodException noSuchMethodException) {

      throw new NoSuchMethodError(noSuchMethodException.getMessage());

    } catch (ClassNotFoundException classNotFoundException) {

      throw new NoClassDefFoundError(classNotFoundException.getMessage());

    } 

  }

}

使用

IFactory factory = (IFactory) company.getProxyInstance();

ProxyUtils.generateClassFile(IFactory.class, factory.getClass().getSimpleName())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值