zoukankan      html  css  js  c++  java
  • JDK动态代理堆栈图详解--干货

    首先我们有一个数据源模型命名为User,其中包括username 和 password这两个属性 和他们的set get方法
    public class User {
        private String username;
        private String password;
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }
    

      

    接着一个UserDAO接口
    public interface UserDAO {
        public void save(User user);
        public void delete();
    }
    

      

    在一个实现该接口的类
    public class UserDAOImpl implements UserDAO {
     
        public void save(User user) {
     
            System.out.println("user saved!");
        }
     
        public void delete() {
            System.out.println("user deteleted");
     
        }
     
    }
    

      

    接着就是动态代理了 实现invocationHandler的类
    public class LogInterceptor implements InvocationHandler {
        private Object target;
     
        public Object getTarget() {
            return target;
        }
     
        public void setTarget(Object target) {
            this.target = target;
        }
     
        public void beforeMethod(Method m) {
     
            System.out.println(m.getName() + " start");
        }
     
        public Object invoke(Object proxy, Method m, Object[] args)
                throws Throwable {
            beforeMethod(m);
            m.invoke(target, args);
            return null;
        }
    }
    

      

    最后我们采取单元测试了 写一个单元测试
    @Test
        public void testProxy() {
            UserDAO userDAO = new UserDAOImpl();
            LogInterceptor li = new LogInterceptor();
            li.setTarget(userDAO);
            UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
            System.out.println(userDAOProxy.getClass());
            System.out.println(userDAOProxy.getClass().getInterfaces());
            userDAOProxy.delete();
            userDAOProxy.save(new User());
     
        }
    

      

    当调用这句话的时候
    UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
    我们创建了一个代理对象userDAOProxy
    当执行该句的时候 userDAOProxy.delete();  userDAOProxy对象是由Proxy的静态方法newProxyInstance产生的,该方法后面跟着三个参数分别为
    userDAO的类加载器,类的所有接口,和一个实现了invocationHandler 的类LogInterceptor
    执行步骤如下 
    1 执行LogInterceptor对象的invoke方法
    2 invoke方法的第一条语句为beforeMethod(m);故跳转至beforeMethod(m);函数
    3执行beforeMethod(m)函数的System.out.println(m.getName() + " start")语句 console中打印出了delete start
    在这里为什么是delete呢,因为我们上面执行的是userDAOProxy.delete()方法,故m.getName()中的m就是delete方法
    beforeMethod(m);执行完毕
    4 执行m.invoke(target, args);
    如上图所示直接跳到了UserDAOImpl实例的delete方法 打印台输出该方法的输出user deteleted
    重新回到invoke方法的 m.invoke(target, args);语句
    一个动态代理的过程就结束了。
    从这个过程宗我们可以看到 当我们使用动态代理对象的方法时候,首先回去调用invoke方法,该方法有参数Method m,也就是我们使用的方法。
    我们在该invoke方法中会加入横向切面逻辑如上面的例子beforeMethod(Method m)方法,该逻辑执行完后通过调用m.invoke(target, args)去执行被代理对象中我们原有的方法。一个代理过程就完成了
    下面是我针对这整个项目画的一个图 应该更加方便理解
  • 相关阅读:
    C++中 结构体和类的异同
    c++sizeof大全
    10th week task -3 Arrow function restore
    10th week task -2 Object 的起源
    js 的起源故事
    10th week task -1
    9th week -the history of program 1950~2020
    javascript统计一个字符在一段字符串出现次数
    Grid layout
    BOM DOM区别 来源
  • 原文地址:https://www.cnblogs.com/winAlaugh/p/5360448.html
Copyright © 2011-2022 走看看