java中动态反射

java中动态反射能达到的效果和python的语法糖很像,能够截获方法的实现,在真实方法调用之前和之后进行修改,甚至能够用自己的实现进行特别的替代,也可以用其实现面向切片的部分功能。动态代理可以方便实现AOP,AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等。

JDK默认的动态代理机制基于interface,而使用CGLib可以实现对类的动态代理功能。JDK动态代理机制涉及到几个地方:

  (1) Proxy类

      Proxy类提供了用于创建动态代理类和实例对象的方法,它是所创建的动态代理类的父类,它最常用的方法如下:

  • public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces):该方法用于返回一个Class类型的代理类,在参数中需要提供类加载器并需要指定代理的接口数组(与真实主题类的接口列表一致)。
  • public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces, InvocationHandler h):该方法用于返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示代理类所实现的接口列表(与真实主题类的接口列表一致),第三个参数h表示所指派的调用处理程序类。

   (2) InvocationHandler接口

      InvocationHandler接口是代理处理程序类的实现接口,该接口作为代理实例的调用处理者的公共父类,每一个代理类的实例都可以提供一个相关的具体调用处理者(InvocationHandler接口的子类)。在该接口中声明了如下方法:

  • public Object invoke(Objectproxy, Method method, Object[] args):该方法用于处理对代理类实例的方法调用并返回相应的结果,当一个代理实例中的业务方法被调用时将自动调用该方法。invoke()方法包含三个参数,其中第一个参数proxy表示代理类的实例,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组。

        动态代理类需要在运行时指定所代理真实主题类的接口,客户端在调用动态代理对象的方法时,调用请求会将请求自动转发给InvocationHandler对象的invoke()方法,由invoke()方法来实现对请求的统一处理。

下面的这个例子,在每个方法前后分别打印日志,说明该方法开始执行,在改方法结束的时候打印日志方法结束。如果不采用动态代理机制,则需要在每个方法的开始和结束的位置都加上类似的日志,有了代理机制以后只用一句话。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface TestInterface {
	void print(String p);

	void filter();

	void say(String string);
}

class TestImpl implements TestInterface {

	public void say(String to) {
		System.out.println("Say hello to " + to);
	}

	public void print(String s) {
		System.out.println("print : " + s);
	}

	public void filter() {
		System.out.println("filter");
	}
}

class LogHandler implements InvocationHandler {
	private Object dele;

	public LogHandler(Object obj) {
		this.dele = obj;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String funcname = method.getName();
		// 这里过滤掉filter方法,什么都不做
		if (method.getName().equals("filter")) {
			System.out.println(method.getName() + " filter,not execute");
			return null;
		}
		beforeFunction(funcname);
		Object result = method.invoke(dele, args);
		endFunction(funcname);
		return result;
	}

	private void beforeFunction(String funcname) {
		System.out.println("method:" + funcname + " begins.");
	}

	private void endFunction(String funcname) {
		System.out.println("method:" + funcname + " ends.");
	}
}

public class ProxyTest {

	public static void main(String[] args) {
		TestImpl impl = new TestImpl();
		LogHandler handler = new LogHandler(impl);
		// 这里把handler与impl新生成的代理类相关联
		TestInterface testinter = (TestInterface) Proxy.newProxyInstance(impl.getClass().getClassLoader(),
				impl.getClass().getInterfaces(), handler);
		// 这里无论访问哪个方法,都是会把请求转发到handler.invoke
		testinter.print("All the test");
		testinter.say("Cob");
		// 这里过滤掉filter方法,什么都不返还
		testinter.filter();
	}

}

  

 

posted @ 2016-06-21 17:45  唠叨阁大学士  阅读(236)  评论(0编辑  收藏  举报