【ThinkingInJava】43、与动态代理混合的装饰器模式

//: net/mindview/util/TwoTuple.java
package net.mindview.util;

public class TwoTuple<A,B> {
  public final A first;
  public final B second;
  public TwoTuple(A a, B b) { first = a; second = b; }
  public String toString() {
    return "(" + first + ", " + second + ")";
  }
} ///:~


package Lesson15_generices;

//: generics/Mixins.java
import java.util.*;

interface TimeStamped { long getStamp(); }

class TimeStampedImp implements TimeStamped {
  private final long timeStamp;
  public TimeStampedImp() {
    timeStamp = new Date().getTime();
  }
  public long getStamp() { return timeStamp; }
}

interface SerialNumbered { long getSerialNumber(); }

class SerialNumberedImp implements SerialNumbered {
  private static long counter = 1;
  private final long serialNumber = counter++;
  public long getSerialNumber() { return serialNumber; }
}

interface Basic {
  public void set(String val);
  public String get();
}

class BasicImp implements Basic {
  private String value;
  public void set(String val) { value = val; }
  public String get() { return value; }
}

class Mixin extends BasicImp
implements TimeStamped, SerialNumbered {
  private TimeStamped timeStamp = new TimeStampedImp();
  private SerialNumbered serialNumber =
    new SerialNumberedImp();
  public long getStamp() { return timeStamp.getStamp(); }
  public long getSerialNumber() {
    return serialNumber.getSerialNumber();
  }
}

public class Mixins {
  public static void main(String[] args) {
    Mixin mixin1 = new Mixin(), mixin2 = new Mixin();
    mixin1.set("test string 1");
    mixin2.set("test string 2");
    System.out.println(mixin1.get() + " " +
      mixin1.getStamp() +  " " + mixin1.getSerialNumber());
    System.out.println(mixin2.get() + " " +
      mixin2.getStamp() +  " " + mixin2.getSerialNumber());
  }
} /* Output: (Sample)
test string 1 1132437151359 1
test string 2 1132437151359 2
*///:~

/**
* 书本:《Thinking In Java》
* 功能:与动态代理混合
* 文件:DynamicProxyMixin.java
* 时间:2015年4月21日10:38:44
* 作者:cutter_point
*/
package Lesson15_generices;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

import net.mindview.util.TwoTuple;

import static net.mindview.util.Tuple.*;

class MixinProxy implements InvocationHandler
{
	Map<String, Object> delegetesByMethod;
	
	public MixinProxy(TwoTuple<Object, Class<?>>... pairs)//这句表示,多个TwoTuple<Object, Class<?>>类型的参数
	{
		delegetesByMethod = new HashMap<String, Object>();
		for(TwoTuple<Object, Class<?>> pair : pairs)
		{
			for(Method method : pair.second.getMethods())	//取得这个类的所有方法,遍历
			{
				String methodName = method.getName();
				if(!delegetesByMethod.containsKey(methodName))	//如果这个map包含这个指定键就返回true
					delegetesByMethod.put(methodName, pair.first);	//吧有这个方法的类放进去和这个方法形成映射
			}
		}
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable
	{
		String methodName = method.getName();	//取得方法的名字
		Object delegate = delegetesByMethod.get(methodName);	//根据方法名取得对应的方法
		System.out.println("动态代理里面的invoke方法");
		return method.invoke(delegate, args);	//回调
	}
	
	public static Object newInstance(TwoTuple... pairs)
	{
		Class interfaces[] = new Class[pairs.length];	//创建长度为pairs.length的Class数组
		for(int i = 0; i < pairs.length; ++i)
		{
			interfaces[i] = (Class)pairs[i].second;	//取得所有的类的方法,初始化这个数组,里面存放的是第二个参数,这里应该是类型信息
		}
		
		//取得c1的类加载器,让代理类实现的时候使用同一个类加载器
		ClassLoader cl = pairs[0].first.getClass().getClassLoader();
		
		//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
		/**
		 * c1是代理对象使用的加载类,interfaces是代理类要实现的接口列表,第三个参数new MixinProxy(pairs)是指派方法调用的调用处理程序 
		 */
		return Proxy.newProxyInstance(cl, interfaces, new MixinProxy(pairs));
	}
}

public class DynamicProxyMixin
{

	public static void main(String[] args)
	{
		Object mixin = MixinProxy.newInstance(
				tuple(new BasicImp(), Basic.class),
			      tuple(new TimeStampedImp(), TimeStamped.class),
			      tuple(new SerialNumberedImp(),SerialNumbered.class));
		
		Basic b = (Basic)mixin;
		TimeStamped t = (TimeStamped)mixin;
	    SerialNumbered s = (SerialNumbered)mixin;
	    b.set("cutter_point");	//调用set方法的时候,代理拦截,在实现之前执行代理
	    System.out.println(b.get());	//调用get方法了,再次触发
	    System.out.println(t.getStamp());	//同上
	    System.out.println(s.getSerialNumber());	//同上

	}
}

输出:

动态代理里面的invoke方法
动态代理里面的invoke方法
cutter_point
动态代理里面的invoke方法
1431995142154
动态代理里面的invoke方法
1








郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。