• Java基础之反射生成JDK动态代理


    在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口。通过这个类和接口可以生成JDK动态代理类或动态代理对象。

    JDK动态代理例子:

    // 抽象主题角色
    public interface Sleep {
        void sleep();
    }
      
    // 真实主题角色
    public class SleepImpl implements Sleep {
        @Override
        public void sleep() {
            System.out.println("熟睡中");
        }
    }
      
    //动态处理器
    public class DynamicProxyHandler implements InvocationHandler {   
        private Object obj ;
        public  DynamicProxyHandler(final Object obj) {       
            this.obj = obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("睡觉前要刷牙");
            Object result = method.invoke(obj, args);
            System.out.println("睡醒后要吃早饭");
            return null;
        }
    }
    //测试代码
    public class ProxyTest {
        public static void main(String[] args) {              
            Sleep sleep = new SleepImpl();
            DynamicProxyHandler dph = new DynamicProxyHandler(sleep);
            Sleep sleepProxy = (Sleep) Proxy.newProxyInstance(sleep.getClass().getClassLoader(),
                    sleep.getClass().getInterfaces(), dph);
            sleepProxy.sleep();
        }
    }
      
    结果:睡觉前要刷牙
          熟睡中
          睡醒后要吃早饭

    JDK动态代理源码分析:

    生产代理类主要是通过:Proxy.newProxyInstance方法:

    @CallerSensitive
        public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
            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.
             */
            Class<?> cl = getProxyClass0(loader, intfs);
     
            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }
     
                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);
            }
        }
  • 相关阅读:
    PHP使用引用变量foreach时,切记其他循环不要使用同一个名字的变量
    PHP 获取给定时间的周日时间或月末时间或每天
    MySQL Load Data InFile 文件内容导入数据库和 Into OutFile导出数据到文件
    直接拿来用!最火的iOS开源项目(一)
    12个有趣的C语言问答
    Flex,Flash,AS3,AIR的关系和区别
    Stage3D大冒险
    c/c++程序中内存区划分
    IOS—— strong weak retain assign 学习
    如何提高你的移动开发中AS3/AIR性能
  • 原文地址:https://www.cnblogs.com/jnba/p/10522670.html
Copyright © 2020-2023  润新知