2015-09-07 11:44:36 -06:00
|
|
|
|
// generics/DynamicProxyMixin.java
|
2015-11-14 16:18:05 -08:00
|
|
|
|
// <20>2016 MindView LLC: see Copyright.txt
|
2015-11-15 15:51:35 -08:00
|
|
|
|
// We make no guarantees that this code is fit for any purpose.
|
|
|
|
|
// Visit http://mindviewinc.com/Books/OnJava/ for more book information.
|
2015-06-15 17:47:35 -07:00
|
|
|
|
import java.lang.reflect.*;
|
|
|
|
|
import java.util.*;
|
2015-11-11 20:20:04 -08:00
|
|
|
|
import onjava.*;
|
|
|
|
|
import static onjava.Tuple.*;
|
2015-06-15 17:47:35 -07:00
|
|
|
|
|
|
|
|
|
class MixinProxy implements InvocationHandler {
|
|
|
|
|
Map<String,Object> delegatesByMethod;
|
|
|
|
|
@SuppressWarnings("unchecked")
|
2015-11-11 20:20:04 -08:00
|
|
|
|
public MixinProxy(Tuple2<Object,Class<?>>... pairs) {
|
2015-06-15 17:47:35 -07:00
|
|
|
|
delegatesByMethod = new HashMap<>();
|
2015-11-11 20:20:04 -08:00
|
|
|
|
for(Tuple2<Object,Class<?>> pair : pairs) {
|
|
|
|
|
for(Method method : pair._2.getMethods()) {
|
2015-06-15 17:47:35 -07:00
|
|
|
|
String methodName = method.getName();
|
|
|
|
|
// The first interface in the map
|
|
|
|
|
// implements the method.
|
|
|
|
|
if(!delegatesByMethod.containsKey(methodName))
|
2015-11-11 20:20:04 -08:00
|
|
|
|
delegatesByMethod.put(methodName, pair._1);
|
2015-06-15 17:47:35 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public Object invoke(Object proxy, Method method,
|
|
|
|
|
Object[] args) throws Throwable {
|
|
|
|
|
String methodName = method.getName();
|
|
|
|
|
Object delegate = delegatesByMethod.get(methodName);
|
|
|
|
|
return method.invoke(delegate, args);
|
|
|
|
|
}
|
|
|
|
|
@SuppressWarnings("unchecked")
|
2015-11-11 20:20:04 -08:00
|
|
|
|
public static Object newInstance(Tuple2... pairs) {
|
2015-06-15 17:47:35 -07:00
|
|
|
|
Class[] interfaces = new Class[pairs.length];
|
|
|
|
|
for(int i = 0; i < pairs.length; i++) {
|
2015-11-11 20:20:04 -08:00
|
|
|
|
interfaces[i] = (Class)pairs[i]._2;
|
2015-06-15 17:47:35 -07:00
|
|
|
|
}
|
|
|
|
|
ClassLoader cl =
|
2015-11-11 20:20:04 -08:00
|
|
|
|
pairs[0]._1.getClass().getClassLoader();
|
2015-06-15 17:47:35 -07:00
|
|
|
|
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("Hello");
|
|
|
|
|
System.out.println(b.get());
|
|
|
|
|
System.out.println(t.getStamp());
|
|
|
|
|
System.out.println(s.getSerialNumber());
|
|
|
|
|
}
|
2015-09-07 11:44:36 -06:00
|
|
|
|
}
|
|
|
|
|
/* Output:
|
2015-06-15 17:47:35 -07:00
|
|
|
|
Hello
|
|
|
|
|
1434408462833
|
|
|
|
|
1
|
2015-09-07 11:44:36 -06:00
|
|
|
|
*/
|