JAVA-动态代理JDK

jdk的动态代理实现是常用的方法之一,动态代理相比较于静态代理的好处不言而喻,可以少写大量的代理类,更加便于扩展。下面用一个样例来看一下具体实现:

1. 由于实现原理要求,首先需要一个接口

public interface OrderService {

	/**
	 * 添加一个订单
	 * @param o
	 */
	void add(Order o);
	
	/**
	 * 删除一个订单
	 * @param orderNo
	 */
	void delete(String orderNo);
}

 

public class Order {
	
	private String orderNo;
	
	private String orderName;
	
	public Order(String orderNo, String orderName) {
		super();
		this.orderNo = orderNo;
		this.orderName = orderName;
	}

	
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("[orderNo=");
		builder.append(orderNo);
		builder.append(", orderName=");
		builder.append(orderName);
		builder.append("]");
		return builder.toString();
	}
}

2. 接口实现

public class OrderServiceImpl implements OrderService {

	@Override
	public void add(Order o) {
		System.out.println("add a order" + o.toString());
	}

	@Override
	public void delete(String orderNo) {
		System.out.println(String.format("delete a order[orderNo=%s]", orderNo));
	}
}

 3. 创建代理工厂

public class OrderProxyFactory implements InvocationHandler {

	private Object target;
		
	public OrderProxyFactory(Object target) {
		super();
		this.target = target;
	}

	/**
	 * 获取代理类
	 * @return $Proxy0对象
	 */
	@SuppressWarnings("unchecked")
	public <T> T getProxy() {
		return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
	
	/**
	 * 添加代理方法的额外信息
	 * proxy $Proxy0对象
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("order handler before...");
		Object result = method.invoke(target, args); 
		// 这样会出现死循环
//		Object result = method.invoke(proxy, args); 
		System.out.println("order handler after...");
		return result;
	}

}

4.测试

public static void main(String[] args) {
		// 代理类的字节码内容保存在了项目根目录下
//		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
		
		OrderProxyFactory orderProxyFactory = new OrderProxyFactory(new OrderServiceImpl());
		OrderService orderServiceProxy = orderProxyFactory.getProxy();
		System.out.println(orderServiceProxy.getClass());
		orderServiceProxy.add(new Order("111", "手机"));
		orderServiceProxy.delete("111");
	}

 输出:

class com.sun.proxy.$Proxy0
order handler before...
add a order[orderNo=111, orderName=手机]
order handler after...
order handler before...
delete a order[orderNo=111]
order handler after...

 

5.  原理分析

重点在于Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法,方法实现如下:

@CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        // 1.会根据传入的interfaces生成代理类
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            // 2.获取实现类的构造函数
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            // 3.实例化代理类,注意此处会将传入的h(OrderProxyFactory实例)保存到实例中
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

从方法实现中可以知道,该方法会生成一个OderService接口的实现类,并生成该类一个实例,注意该实例保存了OrderProxyFactory实例,通过设置环境变量"sun.misc.ProxyGenerator.saveGeneratedFiles",可以得到生成的代理类如下: 

public final class $Proxy0 extends Proxy implements OrderService {
	private static final long serialVersionUID = -6310918168123410007L;
	private static Method m1;
	private static Method m2;
	private static Method m3;
	private static Method m4;
	private static Method m0;

	public $Proxy0(InvocationHandler var1) {
      super(var1);
   }

	public final boolean equals(Object var1) {
      try {
         return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
      } catch (RuntimeException | Error var3) {
         throw var3;
      } catch (Throwable var4) {
         throw new UndeclaredThrowableException(var4);
      }
   }

	public final String toString() {
      try {
         return (String)super.h.invoke(this, m2, (Object[])null);
      } catch (RuntimeException | Error var2) {
         throw var2;
      } catch (Throwable var3) {
         throw new UndeclaredThrowableException(var3);
      }
   }

	public final void add(Order var1) {
      try {
         // 1. 此处会调用InvocationHandler(传入的OrderProxyFactory)的invoke方法
         // 2. 此处的this就是$Proxy0实例
         // 3. 从下面静态代码块中可以知道m3就是add方法
         super.h.invoke(this, m3, new Object[]{var1});
      } catch (RuntimeException | Error var3) {
         throw var3;
      } catch (Throwable var4) {
         throw new UndeclaredThrowableException(var4);
      }
   }

	public final void delete(String var1) {
      try {
         super.h.invoke(this, m4, new Object[]{var1});
      } catch (RuntimeException | Error var3) {
         throw var3;
      } catch (Throwable var4) {
         throw new UndeclaredThrowableException(var4);
      }
   }

	public final int hashCode() {
      try {
         return (Integer)super.h.invoke(this, m0, (Object[])null);
      } catch (RuntimeException | Error var2) {
         throw var2;
      } catch (Throwable var3) {
         throw new UndeclaredThrowableException(var3);
      }
   }

	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("com.core.proxy.jdk.OrderService").getMethod("add",
					Class.forName("com.core.proxy.jdk.Order"));
			m4 = Class.forName("com.core.proxy.jdk.OrderService").getMethod("delete",
					Class.forName("java.lang.String"));
			m0 = Class.forName("java.lang.Object").getMethod("hashCode");
		} catch (NoSuchMethodException var2) {
			throw new NoSuchMethodError(var2.getMessage());
		} catch (ClassNotFoundException var3) {
			throw new NoClassDefFoundError(var3.getMessage());
		}
	}
}

 

 从上面生成的代理类就可以清楚的知道JDK动态代理的实现关键之处就是生成了指定接口的实现类,也就可以知道JDK的这种实现为什么必须要有一个接口的原因,还是对于新手来说上面可能出现的死循环的原因,至于怎么生成的$Proxy0的代理类(利用ProxyGenerator),感兴趣的同学可以去研究一下

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值