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

    一:前言

      自己在稳固spring的一些特性的时候在网上看到了遮掩的一句话“利用接口的方式,spring aop将默认通过JDK的动态代理来实现代理类,不适用接口时spring aop将使用通过cglib 来实现代理类",我对JDK的动态代理机制其实一点都不了解,学习java的时候也是只是知道会用,会去查api的文档就行,所以这些底层的操作方式我自己不是很清楚,现在既然要了解一些底层的代码,就谢谢自己的想发,大部分都是差不多的。

    二:实现

      先给出接口和实现类的代码:

    UserDao.java:

    package dynamicProxy;
    
    public interface UserDao {
        String saveUser(String name);
        void deleteUser(String name);
    }

    UserDaoImpl.java:

    package dynamicProxy;
    
    public class UserDaoImpl implements UserDao{
    
        @Override
        public String saveUser(String name) {
            System.out.println("姓名:"+name);
            return name;
        }
    
        @Override
        public void deleteUser(String name) {
                System.out.println("要删除的姓名:"+name);        
        }
        
    }

    既然都说了是JDK的动态代理,那么现在我们需要些一个累来实现"java.lang.reflect.InvocationHandler"的接口,里面有invoke(*,*,*)方法,该方法有三个参数,参数意思下面会说给出代码如下:

    package dynamicProxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class MouseHandler implements InvocationHandler {
        
        private Object target;
        
        public MouseHandler(Object target) {
            this.target = target;
        }
    
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println("代理的类为:"+proxy.getClass());
            System.out.println("目标类:"+target.getClass()+"target对象--->"+target);
            System.out.println("方法:"+method);
            System.out.println("参数:"+args);
            System.out.println("开始输出日志");
            Object obj=method.invoke(target, args);
            System.out.println("obj的值:"+obj);
            return obj;
        }
    
    }

    当你自己把这些参数全部打印出来了,就会知道参数的意思。下面我写下来了

    Object proxy:要代理的类(打印结果为------>代理的类为:class $Proxy0)

    Method method:这里的method是指要调用得方法(打印结果-------->方法:public abstract java.lang.String dynamicProxy.UserDao.saveUser(java.lang.String))

    Object[] args:这里是参数数组,就是该方法的参数

    还有就是这个方法(public Object invoke(Object proxy, Method method, Object[] args))最后我们返回的值:返回的值就是我们调用该方法,该方法返回的值 (输出结果为---->obj的值:老鼠)

    再来说说这和Object proxy,如果你在method.invoke(proxy,args)这里的第一个参数依然使用proxy(自动生成的代理类)的话,在运行程序你会发现程勋会一会运行(报错),一直循环,错误代码如下:

    这里需要指定要代理的对象。

    下面在看看Test.java类

    package dynamicProxy;
    
    import java.lang.reflect.Proxy;
    
    public class Test {
        public static void main(String args[]){
            UserDao userDao=new UserDaoImpl();
            
            System.out.println("-->"+userDao.getClass().getClassLoader());//(打印结果:-->sun.misc.Launcher$AppClassLoader@addbf1)
            System.out.println("-->"+userDao.getClass().getInterfaces());//(打印结果:-->[Ljava.lang.Class;@61de33)
            UserDao userDaoProxy=(UserDao)Proxy
            .newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces()
                    , new MouseHandler(userDao));
            userDaoProxy.saveUser("老鼠");
            
        }
            
    }

    看看Proxy(*,*,*)方法中的三个参数

    userDao.getClass().getClassLoader():这是类加载器
     userDao.getClass().getInterfaces():代理的接口
    new MouseHandler(userDao):实例化传入需要代理的对象(对UserDaoImpl的引用)

    如果你再加断点调试的话就会发现,其实MouseHandler中的invoke方法只有在调用方法
    userDaoProxy.saveUser("老鼠");的时候才会执行,也就是说调用得是saveUser("老鼠"),实际上时在调用invoke方法。上面的知识其实有的也是看看网上的资料,在结合下来写的,但是真正需要自己断点来运行下
      其实现在我在理解底层代码,很多都是需要自己来敲一遍,自己断点运行,自己来调试,只有这样自己的理解才会会更加的彻底。这几天算是把spring ioc和aop给理解了一遍,IOC还好,但是aop自己觉得理解起来好是郁闷啊。不过我还是回尽量的去理解,这对自己还是有好处的。明天就是我自己的生日了,这是我出社会(还未毕业的出社会)第一次过生日,写篇博客提前祝自己生日快乐吧。实习已经快3个月了,不敢说自己现在又多么多么的牛逼,但是真的觉得自己进步了,自己有了方向感,自己知道需要去学习些什么东西。这一点很是重要。以前虽然也知道要学java,但是只是懂了皮毛,真正的东西还是不理解。这就是基础。最近在补习很多东西,java、linux、计算机网络等。还有好远的路要走啊。明天在写篇自己这块三个月的感感想吧。记录下自己的感受。努力加油,一天一天的进步。努力!!!
  • 相关阅读:
    mongodb 的云数据库产品 mlab 的使用
    koa 项目实战(十一)验证登录和注册的 input
    koa 项目实战(十)使用 validator 验证表单
    koa 项目实战(九)passport验证token
    koa 项目实战(八)生成token
    koa 项目实战(七)登录接口
    koa 项目实战(六)注册接口加密
    koa 项目实战(五)全球公用头像的使用
    [C++] 用Xcode来写C++程序[4] 函数
    [控件] 将字符串转换成贝塞尔曲线并执行动画
  • 原文地址:https://www.cnblogs.com/wuhao1991/p/4024777.html
Copyright © 2011-2022 走看看