zoukankan      html  css  js  c++  java
  • jdk动态代理学习

    在jdk的好多底层代码中很多都使用jdk的动态代理,下面就写写简单的代码来look look.

    老规矩先上代码:

    public interface SayDao {
        public String sayChinese();
        public String sayEnglish();
    }
    View Code
    public class SayDaoImpl implements SayDao {
        @Override
        public String sayChinese() {
    
            return "我就是我!";
        }
    
        @Override
        public String sayEnglish() {
            return "I am tom_plus!";
        }
    }
    View Code
    public class JDBCProxy implements InvocationHandler {
        private Object target;
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("invoke begin!");
            return method.invoke(target,args);
        }
        public Object bind(Object target) {
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
        }
    }
    View Code
    public class JDBCProxyTest {
        public static void main(String[] args) {
            JDBCProxy jdbcProxy = new JDBCProxy();
            SayDao sayDao = (SayDao) jdbcProxy.bind(new SayDaoImpl());
            String s = sayDao.sayChinese();
            System.out.println(s);
            System.out.println("----------------");
            printClassDefinition(sayDao.getClass());
        }
        public static String getModifier(int modifier) {
            String result = "";
            switch(modifier){
                case Modifier.PRIVATE:
                    result = "private";
                case Modifier.PUBLIC:
                    result = "public";
                case Modifier.PROTECTED:
                    result = "protected";
                case Modifier.ABSTRACT :
                    result = "abstract";
                case Modifier.FINAL :
                    result = "final";
                case Modifier.NATIVE :
                    result = "native";
                case Modifier.STATIC :
                    result = "static";
                case Modifier.SYNCHRONIZED :
                    result = "synchronized";
                case Modifier.STRICT  :
                    result = "strict";
                case Modifier.TRANSIENT :
                    result = "transient";
                case Modifier.VOLATILE :
                    result = "volatile";
                case Modifier.INTERFACE :
                    result = "interface";
            }
            return result;
        }
    
        public static void printClassDefinition(Class clz){
    
            String clzModifier = getModifier(clz.getModifiers());
            if(clzModifier!=null && !clzModifier.equals("")){
                clzModifier = clzModifier + " ";
            }
            String superClz = clz.getSuperclass().getName();
            if(superClz!=null && !superClz.equals("")){
                superClz = "extends " + superClz;
            }
    
            Class[] interfaces = clz.getInterfaces();
    
            String inters = "";
            for(int i=0; i<interfaces.length; i++){
                if(i==0){
                    inters += "implements ";
                }
                inters += interfaces[i].getName();
            }
    
            System.out.println(clzModifier +clz.getName()+" " + superClz +" " + inters );
            System.out.println("{");
    
            Field[] fields = clz.getDeclaredFields();
            for(int i=0; i<fields.length; i++){
                String modifier = getModifier(fields[i].getModifiers());
                if(modifier!=null && !modifier.equals("")){
                    modifier = modifier + " ";
                }
                String fieldName = fields[i].getName();
                String fieldType = fields[i].getType().getName();
                System.out.println("    "+modifier + fieldType + " "+ fieldName + ";");
            }
    
            System.out.println();
    
            Method[] methods = clz.getDeclaredMethods();
            for(int i=0; i<methods.length; i++){
                Method method = methods[i];
    
                String modifier = getModifier(method.getModifiers());
                if(modifier!=null && !modifier.equals("")){
                    modifier = modifier + " ";
                }
    
                String methodName = method.getName();
    
                Class returnClz = method.getReturnType();
                String retrunType = returnClz.getName();
    
                Class[] clzs = method.getParameterTypes();
                String paraList = "(";
                for(int j=0; j<clzs.length; j++){
                    paraList += clzs[j].getName();
                    if(j != clzs.length -1 ){
                        paraList += ", ";
                    }
                }
                paraList += ")";
    
                clzs = method.getExceptionTypes();
                String exceptions = "";
                for(int j=0; j<clzs.length; j++){
                    if(j==0){
                        exceptions += "throws ";
                    }
    
                    exceptions += clzs[j].getName();
    
                    if(j != clzs.length -1 ){
                        exceptions += ", ";
                    }
                }
                exceptions += ";";
                String methodPrototype = modifier +retrunType+" "+methodName+paraList+exceptions;
                System.out.println("    "+methodPrototype );
            }
            System.out.println("}");
        }
    
    }
    View Code

    我的视角:

    动态代理其实就是Proxy类动态的根据指定的所有接口生成一个class,该class会继承Proxy类,并实现所有指定的接口(在参数中传入的接口数组);然后再利用指定的classloader将 class加载进系统,最后生成这样一个类的对象,并初始化该对象的一些值,如invocationHandler,以即所有的接口对应的Method成员。 初始化之后将对象返回给调用的客户端。这样客户端拿到的就是一个实现所有的接口的Proxy对象。

    从代码角度:

    com.sun.proxy.$Proxy0 extends java.lang.reflect.Proxy implements com.springapp.test.SayDao
    {
    java.lang.reflect.Method m1;
    java.lang.reflect.Method m0;
    java.lang.reflect.Method m3;
    java.lang.reflect.Method m4;
    java.lang.reflect.Method m2;

    boolean equals(java.lang.Object);
    java.lang.String toString();
    int hashCode();
    java.lang.String sayChinese();
    java.lang.String sayEnglish();
    }

    具体细节:

    public static Object newProxyInstance(ClassLoader loader,
    Class<?>[] interfaces,
    InvocationHandler h)
    参数一:类加载器,把创建的代理类class加载进系统。
    参数二:被代理对象实现的接口 class数组
    参数三:调度处理程序类,内有invoke()方法,代理的核心就是调InvocationHandler类的invoke(Object proxy, Method method, Object[] args)方法
    ,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
    注意点:Object proxy 这个参数,代表的是代理类对象。
    调用这个方法,返回代理类 class。
  • 相关阅读:
    深入浅出的webpack4构建工具--webpack4+vue+route+vuex项目构建(十七)
    深入浅出的webpack4构建工具---Scope Hoisting(十六)
    深入浅出的webpack4构建工具---webpack+vue+router 按需加载页面(十五)
    深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)
    关于html的a标签的target="__blank "的安全漏洞问题
    深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三)
    深入浅出的webpack构建工具---tree shaking打包性能优化(十二)
    深入浅出的webpack4构建工具---浏览器前端资源缓存(十一)
    vue分页全选和单选操作
    go语言之进阶篇通过range遍历channel内容
  • 原文地址:https://www.cnblogs.com/tom-plus/p/5586757.html
Copyright © 2011-2022 走看看