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

一、反射:

  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

原文地址:https://www.cnblogs.com/baichendongyang/p/13235505.html