zoukankan      html  css  js  c++  java
  • 《Java知识应用》模式实现Java 动态代理

    动态代理说明:将你提供的接口改造成和你这个类有关的代理对象。

    Java动态代理案例和原理:https://www.cnblogs.com/jssj/p/11771408.html

    我们无法像JVM一样不需要生成Java文件直接生成字节码。我们模拟就通过手工生成java,然后编译成Class文件来实现。

    模式案例:

    package demo.knowledgepoints.invocationhandler;
    
    public interface MyInvocationHandler {
        public Object invoke();
    }
    package demo.knowledgepoints.invocationhandler;
    
    public class MyInvocationHandlerImpl implements MyInvocationHandler {
    
        @Override
        public Object invoke() {
            System.out.println("===== MyInvocationHandlerImpl =====");
            return null;
        }
    }
    package demo.knowledgepoints.invocationhandler;
    
    public interface MyService {
        public void query();
    }
    package demo.knowledgepoints.invocationhandler;
    
    public class BinServvice implements MyService {
        @Override
        public void query() {
            System.out.println("===== start BinServvice =======");
        }
    }
    package demo.knowledgepoints.invocationhandler;
    
    public class TaoService implements MyService {
        @Override
        public void query() {
            System.out.println("========= start TaoService ========");
        }
    }
    package demo.knowledgepoints.invocationhandler;
    
    import javax.tools.JavaCompiler;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    
    public class MyProxy {
    
        public static void main(String[] args) {
            try {
                MyInvocationHandler myInvocationHandler = new MyInvocationHandlerImpl();
    
                MyService myService = (MyService) MyProxy.getInstance(new BinServvice(),myInvocationHandler);
                myService.query();
    
                System.out.println("================================================");
    
                myService = (MyService) MyProxy.getInstance(new TaoService(),myInvocationHandler);
                myService.query();
            } catch (Exception e) {
                //
            }
        }
    
        public static Object getInstance(Object target, MyInvocationHandler myInvocationHandler) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            Class clazz = target.getClass().getInterfaces()[0];
            Class myInvocationHandlerClazz = myInvocationHandler.getClass().getInterfaces()[0];
            String interfaceName = clazz.getSimpleName();   //获取接口名称。
            String content = "";
            String line = "
    ";//换行
            String tab = "	";//tab
            /****组装一个类start ***/
            String packageContent = "package demo.knowledgepoints.invocationhandler;" + line;
            String importContent = "import " + clazz.getName() + ";" + line
                                  +"import " + myInvocationHandlerClazz.getName() + ";" + line;
            String clazzFirstLineContent = "public class $ProxyMy implements " + interfaceName + "{" + line;
            String myInvocationHandlerName= myInvocationHandlerClazz.getSimpleName();
            String filedContent = tab + "private " + interfaceName + " target;" + line
                    + tab + "private " + myInvocationHandlerName + " myInvocationHandler;" + line;
            String constructorContent = tab + "public $ProxyMy (" + interfaceName + " target,"+myInvocationHandlerName+" myInvocationHandler){" + line
                    + tab + tab + "this.target =target;"
                    + line + tab + tab + "this.myInvocationHandler = myInvocationHandler;"
                    + line + tab + "}" + line;
    
    
            String methodContent = "";
            /**获取传入接口中的全部方法***/
            Method[] methods = clazz.getDeclaredMethods();
            /**循环组装接口中的各个方法**/
            for (Method method : methods) {
                //返回值类型
                String returnTypeName = method.getReturnType().getSimpleName();
                //方法名称
                String methodName = method.getName();
                // 参数类型的数组(int,String等)
                Class args[] = method.getParameterTypes();
                String argsContent = "";
                String paramsContent = "";
                int flag = 0;
                for (Class arg : args) {
                    //String
                    String temp = arg.getSimpleName();
                    //String
                    //String p0
                    argsContent += temp + " p" + flag + ",";
                    //p0
                    paramsContent += "p" + flag + ",";
                    flag++;
                }
                if (argsContent.length() > 0) {
                    argsContent = argsContent.substring(0, argsContent.lastIndexOf(",") - 1);
                    paramsContent = paramsContent.substring(0, paramsContent.lastIndexOf(",") - 1);
                }
    
                methodContent += tab + "public " + returnTypeName + " " + methodName + "(" + argsContent + ") {" + line
                        + tab + tab + "myInvocationHandler.invoke();" + line
                        + tab + tab + "target." + methodName + "(" + paramsContent + ");" + line
                        + tab + "}" + line;
    
            }
            content += packageContent + importContent + clazzFirstLineContent + filedContent + constructorContent + methodContent + "}";
            /****组装一个类end ***/
    
            /****将上述组装的类写入文件中***/
            File file = new File("d:\Study\AcceleateWorld\study\MyProcedure\src\demo\knowledgepoints\invocationhandler\$ProxyMy.java");
            try {
                if (!file.exists()) {
                    file.createNewFile();
                }
                FileWriter fw = new FileWriter(file);
                fw.write(content);
                fw.flush();
                fw.close();
            } catch (Exception e) {
    
            }
            /***使用JavaCompiler对象需要安装JDK,只有JAR无法使用**/
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
            Iterable units = fileMgr.getJavaFileObjects(file);
            JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
            t.call();
            fileMgr.close();
    
            /***将对象new出来读取到内存中***/
            URL[] urls = new URL[]{new URL("file:d:\Study\AcceleateWorld\study\MyProcedure\src\\")};
            URLClassLoader urlClassLoader = new URLClassLoader(urls);
            Class cls = urlClassLoader.loadClass("demo.knowledgepoints.invocationhandler.$ProxyMy");
            Class[] classes = new Class[]{clazz,myInvocationHandlerClazz};
            Constructor constructor = cls.getConstructor(classes);
            Object o  = constructor.newInstance(target,myInvocationHandler);
            return  o;
        }
    }

    运行效果:

    生成的代理java文件和Class文件:

    This moment will nap, you will have a dream; But this moment study,you will interpret a dream.
  • 相关阅读:
    js复习(一)
    Webform(文件上传)
    Webform(分页与组合查询配合使用)
    Webform(分页、组合查询)
    webform(内置对象)
    Webform(内置对象-Response与Redirect、QueryString传值、Repeater删改)
    Webform(Repeater控件)
    MDI窗体容器 权限设置
    进程和线程
    WinForm三级联动
  • 原文地址:https://www.cnblogs.com/jssj/p/12499086.html
Copyright © 2011-2022 走看看