java动态代理的使用

来源:互联网 发布:hive sql contains 编辑:程序博客网 时间:2024/05/09 19:03

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

public interface TestI {void test();}

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

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

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

public class TestProxy implements InvocationHandler {private Object tarObj;public TestProxy() {}public TestProxy(Object tarObj) {this.tarObj = tarObj;}@Overridepublic 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;}@Overridepublic 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来创建一个新的代理对象,那么序号还是一样的






0 0
原创粉丝点击