{"id":842,"date":"2021-12-18T20:12:37","date_gmt":"2021-12-18T12:12:37","guid":{"rendered":"https:\/\/blog.cauchyschwarz.com\/?p=842"},"modified":"2021-12-18T20:12:42","modified_gmt":"2021-12-18T12:12:42","slug":"java-dynamic-proxies","status":"publish","type":"post","link":"https:\/\/blog.cauchyschwarz.com\/?p=842","title":{"rendered":"Java Dynamic Proxies"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\u5229\u7528InvocationHandler\u63a5\u53e3\u548cProxy\u7c7b\u7684\u9759\u6001\u65b9\u6cd5\u6211\u4eec\u53ef\u4ee5\u5b9e\u73b0\u5bf9\u4efb\u4f55\u4e00\u4e2a\u63a5\u53e3\u5bf9\u8c61\u7684\u52a8\u6001\u4ee3\u7406(\u7c7b\u4f3c\u4e8ewrapper\uff0c\u5c31\u662f\u901a\u8fc7\u5bf9proxy\u7684\u8c03\u7528\u5b9e\u73b0\u5bf9\u771f\u6b63\u8981\u8c03\u7528\u5bf9\u8c61\u7684\u64cd\u4f5c)\uff1a<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">InvocationHandler\u63a5\u53e3\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">package java.lang.reflect;\npublic interface InvocationHandler {\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable;\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Proxy.newProxyInstance\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">Proxy.newProxyInstance(ClassLoader loader, Class&lt;?&gt;[] interfaces, InvocationHandler h)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u8b6c\u5982\uff0c\u5bf9\u4e8eMyInterface\u63a5\u53e3\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">public interface MyInterface {\n    void doSomething ();\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u81ea\u5df1\u5b9e\u73b0\u4e00\u4e2aInvocationHandler\u63a5\u53e3(MyInvocationHandler)\uff0c\u7136\u540e\u901a\u8fc7Proxy.newProxyInstance\u65b9\u6cd5\u8fd4\u56de\u4e00\u4e2aMyInterface\u7c7b\u7684\u52a8\u6001\u4ee3\u7406(\u8fd9\u4e2a\u4ee3\u7406\u5b9e\u73b0\u4e86MyInterface\u7684\u6240\u6709\u65b9\u6cd5\uff0c\u4f46\u662f\u8fd9\u4e2a\u4ee3\u7406\u4e0d\u662f\u4e00\u4e2aMyInterface\u5bf9\u8c61\uff0c\u5b83\u5c31\u662f\u4e00\u4e2a\u4ee3\u7406\u800c\u5df2\uff0c\u4e00\u4e2a\u52a8\u6001\u521b\u5efa\u7684\u7c7b\uff0c\u901a\u8fc7\u8c03\u7528\u8fd9\u4e2a\u4ee3\u7406\u7684\u65b9\u6cd5\u5b9e\u73b0\u8c03\u7528MyInterface\u7684\u65b9\u6cd5)\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">import java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\nimport java.util.Arrays;\n\npublic class MyInvocationHandler implements InvocationHandler {\n\n    @Override\n    public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {\n        \n         Arrays.stream(Thread.currentThread()\n                            .getStackTrace())\n              .forEach(System.out::println);\n        System.out.println(method);\n        \n\n        System.out.println(\"the invoked method: \" + method);\n        return null;\n    }\n\n    public static void main (String[] args) {\n        MyInvocationHandler handler = new MyInvocationHandler();\n\n        MyInterface o = (MyInterface) Proxy.newProxyInstance(\n                            MyInvocationHandler.class.getClassLoader(),\n                            new Class[]{MyInterface.class}, handler);\n        o.doSomething();\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u5728\u4e0a\u8ff0\u4ee3\u7801\u4e2d\uff0c\u8c03\u7528\u4ee3\u7406o\u7684doSomething\u65b9\u6cd5\u65f6\uff0c\u4ee3\u7406o\u4f1a\u8c03\u7528handler\u7684invoke\u65b9\u6cd5\uff0c\u5e76\u4e14\u5206\u522b\u5c06invoke\u7684\u53c2\u6570Object proxy\u8bbe\u7f6e\u4e3a\u4ee3\u7406o\u3001\u53c2\u6570Method method\u8bbe\u7f6e\u4e3adoSomething\u65b9\u6cd5\u3001Object[] args\u8bbe\u7f6e\u4e3a\u8c03\u7528doSomething\u65f6\u4f7f\u7528\u7684\u53c2\u6570\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E7%9A%84%E4%BD%9C%E7%94%A8\">\u52a8\u6001\u4ee3\u7406\u7684\u4f5c\u7528<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9e\u73b0\u6307\u5b9a\u7c7b\u7684wrapper\uff0c\u62e6\u622a\u5bf9\u8be5\u7c7b\u7684\u65b9\u6cd5\u8c03\u7528\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">import java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\n\npublic class MyInterceptor&lt;T&gt; implements InvocationHandler {\n\n    private T t;\n\n    public MyInterceptor(T t) {\n        this.t = t;\n    }\n\n    @Override\n    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n        System.out.println(\"before method call : \" + method.getName());\n        Object result = method.invoke(t, args);\n        System.out.println(\"after method call : \" + method.getName());\n        return result;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public static &lt;T&gt; T getProxy(T t, Class&lt;? super T&gt; interfaceType) {\n        MyInterceptor handler = new MyInterceptor(t);\n        return (T) Proxy.newProxyInstance(interfaceType.getClassLoader(),\n                new Class&lt;?&gt;[]{interfaceType}, handler\n        );\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"http:\/\/www.logicbig.com\/tutorials\/core-java-tutorial\/java-dynamic-proxies\/generic-cache-decorator\/\">\u5bf9\u4e8eJavabean\u7c7b\u578b\u7684\u7c7b\u5b9e\u73b0\u5e26cache\u7684decorator<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">public interface IObject {\n\n  String getData ();\n\n}\n\nimport java.beans.BeanInfo;\nimport java.beans.IntrospectionException;\nimport java.beans.Introspector;\nimport java.beans.PropertyDescriptor;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Proxy;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class GenericCacheDecorator implements InvocationHandler {\n\n    private Map&lt;String, Object&gt; cachedData = new HashMap&lt;&gt;();\n    private Object EMPTY = new Object();\n    private Object obj;\n\n    private GenericCacheDecorator (Object obj) {\n        this.obj = obj;\n        try {\n            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());\n            for (PropertyDescriptor desc : beanInfo.getPropertyDescriptors()) {\n                cachedData.put(desc.getReadMethod()\n                                   .getName(), EMPTY);\n            }\n\n        } catch (IntrospectionException e) {\n            e.printStackTrace();\n        }\n    }\n\n    public static &lt;I, T extends I&gt; I decorate (T t, Class&lt;I&gt; interfaceClass) {\n        GenericCacheDecorator cacheableDecorator = new GenericCacheDecorator(t);\n        return (I) Proxy.newProxyInstance(interfaceClass.getClassLoader(),\n                                          new Class[]{interfaceClass}, cacheableDecorator);\n\n    }\n\n    public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {\n        if (cachedData.containsKey(method.getName())) {\n            Object o = cachedData.get(method.getName());\n            if (o == EMPTY) {\n                Object returned = method.invoke(obj, args);\n                cachedData.put(method.getName(), returned);\n                return returned;\n            } else {\n                return o;\n            }\n        }\n        return method.invoke(args);\n    }\n\n    public static void main (String[] args) {\n        MyObject object = new MyObject();\n        IObject iObject = GenericCacheDecorator.decorate(object, IObject.class);\n        System.out.println(iObject.getData());\n        System.out.println(iObject.getData());\n    }\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u5229\u7528InvocationHandler\u63a5\u53e3\u548cProxy\u7c7b\u7684\u9759\u6001\u65b9\u6cd5\u6211\u4eec\u53ef\u4ee5\u5b9e\u73b0\u5bf9\u4efb\u4f55\u4e00\u4e2a\u63a5\u53e3\u5bf9\u8c61\u7684\u52a8\u6001\u4ee3\u7406(\u7c7b\u4f3c\u4e8ewrapper\uff0c\u5c31\u662f\u901a\u8fc7\u5bf9proxy\u7684\u8c03\u7528\u5b9e\u73b0\u5bf9\u771f\u6b63\u8981\u8c03\u7528\u5bf9\u8c61\u7684\u64cd\u4f5c)\uff1a Invoca&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[87],"class_list":["post-842","post","type-post","status-publish","format-standard","hentry","category-10","tag-java"],"_links":{"self":[{"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=\/wp\/v2\/posts\/842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=842"}],"version-history":[{"count":1,"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=\/wp\/v2\/posts\/842\/revisions"}],"predecessor-version":[{"id":843,"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=\/wp\/v2\/posts\/842\/revisions\/843"}],"wp:attachment":[{"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.cauchyschwarz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}