美文网首页java
Proxy.newProxyInstance

Proxy.newProxyInstance

作者: 知然 | 来源:发表于2020-04-03 13:02 被阅读0次

    简单实现

    Q:通过代理接口的方式进行声明, 然而不通过类实现的方式进行使用,而是使用其他方式实现.
    比如MyBatis 如何做到只定义接口, 逻辑写到xml中,就可以调用接口?
    FeignClient 为什么只做了声明,却可以直接使用接口进行注入?

    A: 其实这些底层都是用于了一个叫做代理的方式来实现的

    比如 现在有一个接口是这样的

    
        interface TestInterface {
    
            String test01();
    
            String test02(String st, String st2);
    
        }
    
    

    借助 代理的方式给他提供方法的实现,需要用到 Proxy.newProxyInstance这个方法

    newProxyInstance,方法有三个参数:

    1. loader : 用哪个类加载器去加载代理对象
    2. interfaces: 动态代理类需要实现的接口
    3. h: InvocationHandler 类型 动态代理方法在执行时,会调用h里面的invoke方法去执行

    loader实例很好获得, 使用getClass().getClassLoader()即可.

    现在来构造一个 interfaces的实例

     new Class[]{TestInterface.class}
    

    构造一个 h的对象

        static class TestProxy implements InvocationHandler {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
              return null;
            }
    

    动态创建一个接口的实例

    
            InvocationHandler h = new TestProxy();
    
            TestInterface obj = (TestInterface) Proxy.newProxyInstance(getClass().getClassLoader(), 
                                      new Class[]{TestInterface.class}, h);
    
    

    以上,就完成了大概调用的编写. 接着来完成接口实现.

    完善TestProxy.invoke方法

    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 假设这里按照不同的需求进行了实现. 
                switch (method.getName()) {
                    case "tet01": {
                        return "invoke==>" + UUID.randomUUID().toString();
                    }
                    case "test02": {
                        return "invoke==>" + Arrays.asList(args);
                    }
                }
                return null;
    
            }
        }
    
    

    完成 方法的调用

    
         InvocationHandler h = new TestProxy();
    
            TestInterface obj = (TestInterface) Proxy.newProxyInstance(getClass().getClassLoader(),
                       new Class[]{TestInterface.class}, h);
    
          //调用接口中的方法.
            String res = obj.test01();
    
            System.out.println(res);
    
    

    简单的封装

    创建一个工厂

        static class TestFactory {
    
            public static <T> T newInstance(Class<T> clazz) {
    
                InvocationHandler h = new TestProxy();
    
                return (T) Proxy.newProxyInstance(TestFactory.class.getClassLoader(), new Class[]{clazz}, h);
            }
    
        }
    

    通过工厂来调用

            TestInterface t = TestFactory.newInstance(TestInterface.class);
    
            String res = t.test02("111", "222");
    
            System.out.println(res);
    

    完整的测试类

    package cn.com.dunlop.util;
    
    import org.junit.Test;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    import java.util.UUID;
    
    public class TestProxyClazz {
    
        interface TestInterface {
    
            String test01();
    
            String test02(String st, String st2);
    
        }
    
    
        static class TestProxy implements InvocationHandler {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                switch (method.getName()) {
                    case "tet01": {
                        return "invoke==>" + UUID.randomUUID().toString();
                    }
                    case "test02": {
                        return "invoke==>" + Arrays.asList(args);
                    }
                }
                return null;
    
            }
        }
    
        static class TestFactory {
    
            public static <T> T newInstance(Class<T> clazz) {
    
                InvocationHandler h = new TestProxy();
    
    
                return (T) Proxy.newProxyInstance(TestFactory.class.getClassLoader(), new Class[]{clazz}, h);
            }
    
        }
    
        @Test
        public void tet01() {
    
            InvocationHandler h = new TestProxy();
    
            TestInterface obj = (TestInterface) Proxy.newProxyInstance(getClass().getClassLoader(),
     new Class[]{TestInterface.class}, h);
    
            String res = obj.test01();
    
            System.out.println(res);
    
        }
    
        @Test
        public void tet02() {
    
            TestInterface t = TestFactory.newInstance(TestInterface.class);
    
            String res = t.test02("111", "222");
    
            System.out.println(res);
    
        }
    }
    
    

    总结

    通过这种代理方式,可以很轻松做到动态创建接口实现类.

    相关文章

      网友评论

        本文标题:Proxy.newProxyInstance

        本文链接:https://www.haomeiwen.com/subject/mhrhphtx.html