• 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之类的框架会把这一部分代码用设计模式解耦出来,但本质上还是这样子的原理。

  • 相关阅读:
    Zookeeper 集群安装
    Jexus部署.Net Core项目
    NetCore1.1+Linux部署初体验
    Linux初学
    高可用Redis服务架构分析与搭建
    前端开发JS白板编程题目若干
    Javascript中的Microtask和Macrotask——从一道很少有人能答对的题目说起
    ES6原生Promise的所有方法介绍(附一道应用场景题目)
    HTML的iframe标签妙用
    漫谈PHP代码规范
  • 原文地址:https://www.cnblogs.com/Theshy/p/7764415.html
Copyright © 2020-2023  润新知