Java Dynamic Proxy

1) Act as a simple log interceptor:

public class DynamicProxy {
	private static final Logger logger = Logger.getLogger(DynamicProxy.class);
	@SuppressWarnings("unchecked")
	@Test
	public void useProxyTest() {
		String str = "Hello world";
		LoggingInvocationHandler handler = new LoggingInvocationHandler(str);
		Comparable<String> obj = (Comparable<String>) Proxy.newProxyInstance(
				this.getClass().getClassLoader(),
				new Class[]{Comparable.class}, handler);
		obj.compareTo("Yes");
	}
	public static class LoggingInvocationHandler implements InvocationHandler {
		private Object targetObject;

		public LoggingInvocationHandler(Object targetObject) {
			this.targetObject = targetObject;
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			logger.info(String.format("Invoking method: [%s], args: [%s]",
					method.getName(), Lists.newArrayList(args)));

			return method.invoke(targetObject, args);
		}
	}
}

 

2) Act as a simple adapter between two different interfaces:

public class DynamicProxy {
	private static final Logger logger = Logger.getLogger(DynamicProxy.class);
	public static interface GreetV1 {
		String greet(String name, String gender) throws IOException;
	}
	public static interface GreetV2 {
		String greet(String username);
	}
	public class GreetAdapter implements InvocationHandler {
		private GreetV1 greetInstance;

		public GreetAdapter(GreetV1 greetInstance) {
			super();
			this.greetInstance = greetInstance;
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			String methodName = method.getName();
			if ("greet".equals(methodName)) {
				String username = (String) args[0];
				String name = lookupName(username);
				String gender = lookupGender(username);
				logger.info(proxy.getClass());
				// ((GreetV2)proxy).greet(username);
				try {
					return greetInstance.greet(name, gender);
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
			} else {
				return method.invoke(greetInstance, args);
			}
		}
		private String lookupGender(String username) {
			// Dummy
			return "Male";
		}

		private String lookupName(String username) {
			// Dummy
			return "Yang";
		}
	}
	@Test
	public void adapterTest() {
		GreetAdapter adapter = new GreetAdapter(new GreetV1() {
			@Override
			public String greet(String name, String gender) throws IOException {
				return String.format("Hello %s[%s]", name, gender);
			}
		});
		GreetV2 greetV2 = (GreetV2) Proxy.newProxyInstance(this.getClass()
				.getClassLoader(), new Class[]{GreetV2.class}, adapter);
		assertEquals("Hello Yang[Male]", greetV2.greet("Yang, Kunlun"));
		logger.info(greetV2.getClass());
	}
}

   The first argument "proxy" in method invoke()  is actually the "greetV2" instance.   

   greetV2 is indeed an instance of an anonymous class who extends java.lang.reflect.Proxy and implements GreetV2 interface.

   And it has an InvocationHandler property which points to  "adapter".

   If we decomment the "((GreetV2)proxy).greet(username)", the "java.lang.StackOverflowError" will occur.

   See simplified Proxy code below:

public class Proxy implements java.io.Serializable {
    protected InvocationHandler h;
    protected Proxy(InvocationHandler h) {
        this.h = h; // As the dynamically generated class extends Proxy, therefore it has this InvocationHandler property.
    }
   public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
    {
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            return newInstance(cons, ih); // creates a new instance that extends java.lang.reflect.Proxy and implements the interfaces passed in.
    }
}

Reference Links:

http://guojuanjun.blog.51cto.com/277646/1221281

http://paddy-w.iteye.com/blog/841798

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值