动态代理

       java动态代理就是动态的为委托类生成代理类,相比静态代理需要预先编写代理类源码,动态代理只需要定义好接口,然后使用反射动态生成指定接口的实现类(代理类)。以下通过一个demo来分析动态代理的实现细节。

       

    步骤1:定义接口并提供接口实现类。

/**
 *	打电话服务接口
 */
interface CallService{
	public void call();
}

/**
 *	发信息服务接口 
 */
interface SendMessageService{
	public void sendMessage();
}

/**
 *	手机服务接口 
 */
interface PhoneService extends CallService, SendMessageService{

}

/**
 *	服务实现类
 */
class PhoneServiceImpl implements PhoneService{
	@Override
	public void call() {
		System.out.println("call----");
	}
	
	@Override
	public void sendMessage() {
		System.out.println("sendMessage----");
	}
}

 

   步骤2:为接口实现类提供代理。

 

/**
 *	代理逻辑
 */
class ServiceHandler implements InvocationHandler{
	
	/**
	 *	被代理对象
	 */
	private PhoneService target;
	
	public ServiceHandler(PhoneService target){
		this.target = target;
	}

	/**
	 * 提供需要被代理执行的逻辑
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		log("begin servie----");  
		Object rtn = method.invoke(target, args);
		log("finish servie----");  
		return rtn;
	}

	private void log(String info){
		System.out.println(new Date() + " : " + info);
	}
}

 

 以上两步已经准备好了接口和代理逻辑,接下来就测试代理的执行结果。

 

public class Demo {
	public static void main(String[] args) throws Exception {
		//创建被代理的对象
		PhoneService target = new PhoneServiceImpl();
		ServiceHandler serviceHandler = new ServiceHandler(target);
		//创建代理对象
		PhoneService proxy = (PhoneService)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), serviceHandler);    
		//通过代理执行业务逻辑
		proxy.call();
		proxy.sendMessage();
	}
}

   

   以上测试代码的执行结果如下:

 

Thu Mar 27 21:40:21 CST 2014 : begin servie----
call----
Thu Mar 27 21:40:21 CST 2014 : finish servie----
Thu Mar 27 21:40:21 CST 2014 : begin servie----
sendMessage----
Thu Mar 27 21:40:21 CST 2014 : finish servie----

 

   Demo1演示了为PhoneServiceImpl 提供动态代理类来打印日志服务,涉及到的相关类的关系如下: 

 

 



       

         InvocationHandler接口定义了invoke(Object proxy, Method method, Object[] args)方法,用户必须实现InvocationHandler接口,实现invoke 方法来提供代理类的处理逻辑。

       

          Proxy类是所有动态生成的代理类的父类,它提供了为接口动态生成代理类及其对象的方法。通过调用Proxy的静态方法newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)为指定接口interfaces生成名为$ProxyN(N由Proxy的计数器确定)的实现类,该实现类中实现了所有接口定义的方法,方法内部实际是对父类Proxy的InvocationHandler 类型成员h调用invoke方法,Proxy相关源代码如下:

 

 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{
        if (h == null) {
            throw new NullPointerException();
        }

        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        //为所有的接口生成一个实现类,并加载生成Class 对象cl
        Class<?> cl = getProxyClass0(loader, interfaces);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            //通过反射获取cl的构造方法,并传入h 构造出代理类实例
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
                // create proxy instance with doPrivilege as the proxy class may
                // implement non-public interfaces that requires a special permission
                return AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        return newInstance(cons, ih);
                    }
                });
            } else {
                return newInstance(cons, ih);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString());
        }
    }

    private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
        try {
            return cons.newInstance(new Object[] {h} );
        } catch (IllegalAccessException | InstantiationException e) {
            throw new InternalError(e.toString());
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString());
            }
        }
    }

 

      跟踪Proxy源码,获取器动态生成的字节码并将其保存到.class文件,然后用jd-gui 反编译字节码文件可得到如下动态代理类代码:

 

package com.hsh.dynamicproxy;

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 PhoneService
{
  private static Method m4;
  private static Method m1;
  private static Method m3;
  private static Method m0;
  private static Method m2;

  public $Proxy0(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  public final void sendMessage()
    throws 
  {
    try
    {
      this.h.invoke(this, m4, null);
      return;
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }

  public final void call()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }

  public final String toString()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }

  static
  {
    try
    {
      m4 = Class.forName("com.hsh.dynamicproxy.PhoneService").getMethod("sendMessage", new Class[0]);
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("com.hsh.dynamicproxy.PhoneService").getMethod("call", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
    }
    throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
  }
}

 

      通过看生成的代理类源码,代理的原理就一目了然了。 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值