现在的位置: 首页 > 综合 > 正文

java动态代理的使用

2018年04月21日 ⁄ 综合 ⁄ 共 1872字 ⁄ 字号 评论关闭

由于动态代理是针对接口的,所以首先需要声明一个接口,该测试接口如下所示

public interface TestI {
	void test();
}

有了接口,就要有实现类,实现类如下所示

public class TestImpl implements TestI {
	@Override
	public void test() {
		System.out.println("目标方法");
	}
}

要使用动态代理,就要创建一个代理类,该代理类实现InvocationHandler,并实现对应的方法

public class TestProxy implements InvocationHandler {
	private Object tarObj;

	public TestProxy() {
	}

	public TestProxy(Object tarObj) {
		this.tarObj = tarObj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("目标方法之前进行操作");
		method.invoke(tarObj, args);
		System.out.println("目标方法之前进行操作");
		return null;
	}
}

invoke为实现的方法,该方法不需要自己调用,当产生好代理对象后,调用目标方法的时候,这个方法会被自动调用,各个参意义如下

proxy:代理对象(也就是下面主方法里的testProxy)

method:该method就是将要调用的真正的方法的Method对象,打印出来的结果是:

public abstract void asdasd.TestI.test()

            (这个和反射机制的method是一回事,具体实现可以看反射机制的相关知识)

args:目标方法对应参数的数组

写好了代理类,接着就是使用了,为了方便,直接在TestProxy类中创建main方法进行测试,该类完整代码如下:

public class TestProxy implements InvocationHandler {
	//所要代理的真实的对象
	private Object tarObj;

	public TestProxy() {
	}

	public TestProxy(Object tarObj) {
		this.tarObj = tarObj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("目标方法之前进行操作");
		//利用反射机制调用真实对象的方法
		method.invoke(tarObj, args);
		System.out.println("目标方法之后进行操作");
		return null;
	}
	
	public static void main(String[] args) {
		TestImpl testImpl = new TestImpl();
		TestProxy testProxy = new TestProxy(testImpl);
		TestI testI = (TestI) Proxy.newProxyInstance(TestI.class.getClassLoader(), new Class[]{TestI.class}, testProxy);
		testI.test();
	}
}

首先创建一个目标对象,即testImpl

接着当成参数传递给代理类,以此来创建一个代理对象,此

newProxyInstance方法返回一个代理对象,该方法有3个参数,意义如下:

ClassLoader:指定由动态代理产生的类由哪个类加载器来加载

Class[]:由动态代理产生的类的class数组(需要是接口)

InvocationHandler:实现InvocationHandler的接口的类的对象

运行程序输出的结果如下:

目标方法之前进行操作

目标方法

目标方法之后进行操作

就这样,一个动态代理的小实例就写好了

ps:

主方法中的testI不是真正的对象,而是一个代理对象,执行System.out.println(testI.getClass().getName());输出的结果如下

com.sun.proxy.$Proxy0 

这就是一个代理对象,除非是代理不同类的对象,所产生的Proxy*才会出现序号不同的情况,如果仅仅是再次使用newProxyInstance来创建一个新的代理对象,那么序号还是一样的




抱歉!评论已关闭.