zoukankan      html  css  js  c++  java
  • JDK的动态代理

    首先建立一个接口类

    public interface Person {
        void study();
    }

    并实现接口

    @Component
    public class Teacher implements Person {
        public Teacher() {
        }
    
        @Override
        public void study() {
            System.out.println("老师正在学习钢琴");
        }
    }

    创建实现Invocation的类,在这个类中实现增强代理类的方法

    public class TestInvocation implements InvocationHandler{
    
    
        private  Object object;
    
        public TestInvocation(Object object)
        {
            this.object = object;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("吃完早餐准备学习了");
            method.invoke(object,args);
            System.out.println("开始健身了");
            return null;
        }
    }

    创建main方法开始测试

    
    
    public static void main(String[] args) {
    //创建需要代理的类
    Person teacher= new Teacher();
    // 创建实现Invocation的对象将需要代理的类关联起来
    TestInvocation invocation = new TestInvocation(teacher);
    //jdk中通过proxynewProxyInstance方法来创建代理类对象
    //第一个参数使用invocationclassLoader来加载代理类的对象
    //第二个参数获取代理类所实现的接口
    //第三个参数将代理类和实现Invcation的接口的类关联起来
    Person teacher1 = (Person)Proxy.newProxyInstance(invocation.getClass().getClassLoader(), teacher.getClass().getInterfaces(), invocation);
    System.out.println(teacher1.getClass().getName());
    teacher1.study();
    }

    打印出的结果

    com.sun.proxy.$Proxy0
    吃完早餐准备学习了
    老师正在学习钢琴
    开始健身了

    system.out.println(teacher1.getClass().getName());
    打印出的是com.sun.proxy.$Proxy0
     public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
    //首先判断实现invocation的类是否为空
            Objects.requireNonNull(h);
    //    复制接口对象
            final Class<?>[] intfs = interfaces.clone();
    //    获取一个安全管理对象
            final SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
            }
    
            /*
             * Look up or generate the designated proxy class.
             */
      //    生成代理类对象此时的对象就为(com.sun.proxy.$Proxy0)
            Class<?> cl = getProxyClass0(loader, intfs);
    
            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }
    //返回Class对象所表示的类的指定公共一个构造对象
                final Constructor<?> cons = cl.getConstructor(constructorParams);
                final InvocationHandler ih = h;
    //    进行反射查看代理类的修饰符
                if (!Modifier.isPublic(cl.getModifiers())) {
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            cons.setAccessible(true);
                            return null;
                        }
                    });
                }
    //    通过反射创建新对象
                return cons.newInstance(new Object[]{h});
            } catch (IllegalAccessException|InstantiationException e) {
                throw new InternalError(e.toString(), e);
            } catch (InvocationTargetException e) {
                Throwable t = e.getCause();
                if (t instanceof RuntimeException) {
                    throw (RuntimeException) t;
                } else {
                    throw new InternalError(t.toString(), t);
                }
            } catch (NoSuchMethodException e) {
                throw new InternalError(e.toString(), e);
            }
        }    

    反射创建的对象为jvm运行的时候创建的一个动态的对象同时转换成

     Person teacher1 = (Person)Proxy.newProxyInstance(invocation.getClass().getClassLoader(), teacher.getClass().getInterfaces(), invocation);
    调用teeacher的方法完成
  • 相关阅读:
    开源项目SMSS发开指南(四)——SSL/TLS加密通信详解(上)
    开源项目SMSS发开指南(三)——protobuf协议设计
    开源项目SMSS开发指南(二)——基于libevent的线程池
    开源项目SMSS开发指南
    萧瑟斩落叶,孤月伴影长
    TCP/IP和Socket开发经验分享
    Linux C++轻量级开发指南
    如何使用threejs实现第一人称视角的移动
    图形辅助,理解递归
    字节的游戏
  • 原文地址:https://www.cnblogs.com/oldzhang1222/p/9519588.html
Copyright © 2011-2022 走看看