• 动态代理,反射的用途及实现


    一、反射:

    1. 反射的概念:动态加载对象,并对对象进行剖析。在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制

    2. 反射的功能:利用Java反射机制我们可以加载一个运行时才得知名称的class,获悉其构造方法,并生成其对象实体,能对其fields设值并唤起其methods。

      1. 在运行时判断任意一个对象所属的类

      2. 在运行时构造任意一个类的对象

      3. 在运行时判断任意一个类所具有的方法和属性

      4. 在运行时调用任意一个对象的方法

    3. 在Java中我们有三种方法可以获取一个对象的反射类:

      1. 通过getClass方法

        在Java中,每一个Object都有一个getClass方法,通过getClass方法我们可以获取到这个对象对应的反射类:

        String s = "ziwenxie";
        Class<?> c = s.getClass();
      2. 通过forName方法

        Class<?> c = Class.forName("java.lang.String");

      3. 使用.class

        Class<?> c = String.class;

    4. 应用场合:在Java程序中许多对象在运行时都会出现两种类型:编译时类型运行时类型
      编译时的类型由声明该对象时使用的类型决定,运行时的类型由实际赋给对象的类型决定
      如:Person p =new Student();
      编译时类型为Person,而运行时为Student

    5. JAVA反射API

      反射API用来生成在当前JAVA虚拟机中的类、接口或者对象的信息。
      Class类:反射的核心类,可以获取类的属性,方法等内容信息。
      Field类:Java.lang.reflect.表示类的属性,可以获取和设置类的中属性值。
      Method类:Java.lang.reflect。表示类的方法,它可以用来获取类中方法的信息或者执行方法
      Construcor类:Java.lang.reflect。表示类的构造方法。

    6. 应用:Struts2配置action,spring的bean注入

    二、动态代理

    首先,代理是一个机制,在代理模式中,代理可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成。

    通过代理可以让代码之间解耦,比如RPC调用,框架内部的寻址、序列化、反序列化等,对于调用者往往是没有太大

    意义的,通过代理,可以提供更加友善的界面。下面看一个列子:

    public class MyDynamicProxy {
        public static  void main (String[] args) {
            HelloImpl hello = new HelloImpl();
            MyInvocationHandler handler = new MyInvocationHandler(hello);
            // 构造代码实例
            Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler);
            // 调用代理方法
            proxyHello.sayHello();
        }
    }
    interface Hello {
        void sayHello();
    }
    class HelloImpl implements  Hello {
        @Override
        public void sayHello() {
            System.out.println("Hello World");
        }
    }
     class MyInvocationHandler implements InvocationHandler {
        private Object target;
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println("Invoking sayHello");
            Object result = method.invoke(target, args);
            return result;
        }
    }
    
    

    上面的代码中,简单实现了动态代理的构建和代理操作。首先,实现了InvocationHandler接口,这个接口里面只有invoke这个方法,每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

    //proxy:  指代我们所代理的那个真实对象
    //method:  指代的是我们所要调用真实对象的某个方法的Method对象
    //args:  指代的是调用真实对象某个方法时接受的参数
    Object invoke(Object proxy, Method method, Object[] args) throws Throwable

    然后主要是以Hello这个接口为纽带,为被调用目标构建代理对象,进而应用程序就可以使用代理对象间接运行调用目标的逻辑,代理为应用插入额外逻辑(这里是 println)提供了便利的入口。可以在invoke方法实现中增加自定义的逻辑实现,实现对被代理类的业务逻辑无侵入。

    这种实现方式很有局限性,它是以接口为中心的,相当于添加了一种对于被调用者没有太大意义的限制。主要看看spring中的JDK动态代理和cglib动态代理。这两者的主要区别是,JDK动态代理主要是创建接口的动态代理,而cglib主要是创建目标类的子类的方式。

    https://www.cnblogs.com/xiaoluo501395377/p/3383130.html

  • 相关阅读:
    [NOI2016] 网格
    [十二省联考2019]春节十二响
    wordcloud的方法参数归纳汇总
    选择困难症
    连通能力
    [Tjoi2017]城市
    bzoj3732 Network
    bzoj3252 攻略
    Noip2018旅行
    [HEOI2015]兔子与樱花
  • 原文地址:https://www.cnblogs.com/baichendongyang/p/13235505.html
Copyright © 2020-2023  润新知