zoukankan      html  css  js  c++  java
  • java核心学习(四十) 使用反射生成JDK动态代理

      java.lang.reflect包下提供了一个Proxy类和InvocationHandler接口,用于生成动态代理类和动态代理对象。

    一、使用Proxy、InvocationHandler创建动态代理

      这里要注意,在java.net包下也有一个Proxy类,不过这个类是用于设置代理服务器的,莫混淆。。

      Proxy提供了如下两个方法创建动态代理类和动态代理实例:

        

      实际上即使采用第一种方法创建动态代理类,如果程序需要通过该代理类来创建对象,依然需要传入一个InvocationHandler对象,也就是说,系统生成的每个代理对象都有一个与之关联的InvocationHandler对象。

    public class ProxyTest {
        public static void main(String[] args){
            MyInvocationHandler invocationHandler = new MyInvocationHandler();
            invocationHandler.setTarget(new Hero());
            Person hero= (Person) Proxy.newProxyInstance(Hero.class.getClassLoader(),Hero.class.getInterfaces(),invocationHandler);
    //        hero.fight();
    //        hero.laugh();
            hero.sayHello("Tom");
            hero.work();
        }
    }
    interface Person{
        void work();
        void sayHello(String name);
    }
    interface FightAble{
        void fight();
    }
    class Hero implements Person,FightAble{
        @Override
        public void fight() {
            System.out.println("hero fight");
        }
    
        @Override
        public void work() {
            System.out.println("hero work");
        }
    
        @Override
        public void sayHello(String name) {
            System.out.println("hello "+name);
        }
        public void laugh(){
            System.out.println("hero laugh");
        }
    }
    class MyInvocationHandler implements InvocationHandler{
        private Object target;
    
        public void setTarget(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("-------正在执行的方法:"+method);
            if(args != null){
                System.out.println("下面是执行该方法传入的实参:");
                for (Object val : args){
                    System.out.println(val);
                }
            }
    
            else {
                System.out.println("调用的方法没有实参");
                method.invoke(target);
            }
            return null;
        }
    }

      注意,java动态代理产生的对象一定要用接口引用指向之,这是由于java的动态代理实际上时使用传入的接口类型创建了新的类,所以在上面代码中不可以用Hero类型指向创建的对象,只能由Person或FightAble类型指向之。看源码就可以发现这一点。

    二、AOP代理

      AOP(面向切面编程),的一种实现方式就是使用java动态代理。

      在上面的代码中实际上已经实现了AOP,对所有代理对象的无实参方法,在执行方法body之前都先执行System.out.println("调用的方法没有实参");只不过这些代码写在了InvocationHandler中,而像Spring之类的框架会把这一部分代码用设计模式解耦出来,但本质上还是这样子的原理。

  • 相关阅读:
    Struts2+Spring3+Mybatis3开发环境搭建
    spring+struts2+mybatis
    【LeetCode】Populating Next Right Pointers in Each Node
    【LeetCode】Remove Duplicates from Sorted Array
    【LeetCode】Remove Duplicates from Sorted Array II
    【LeetCode】Binary Tree Inorder Traversal
    【LeetCode】Merge Two Sorted Lists
    【LeetCode】Reverse Integer
    【LeetCode】Same Tree
    【LeetCode】Maximum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/Theshy/p/7764415.html
Copyright © 2011-2022 走看看