美文网首页
浅谈 java 反射和动态代理

浅谈 java 反射和动态代理

作者: 温驭臣 | 来源:发表于2019-01-03 11:38 被阅读0次

            编程语言通常有各种不同的分类角度,动态类型和静态类型就是其中一种分类角度,简单区分就是语言类型信息是在运行时检查,还是在编译区检查。与其近似的还有一个对比,就是所谓强类型和弱类型,就是不同类型变量赋值时,是否需要显示的(强制)进行类型转换。

            通常认为,java 是静态的强类型型语言,但是因为提供了类似反射等机制,也具备了部分动态类型语言的能力。

    第一,反射

            反射机制是 java 语言提供的一种基础功能,赋予程序在运行时自省(introspect)的能力。通过反射我们可以直接操作类或者对象,比如获取某个对象的类定义,获取类声明的属性和方法,调用方法或者构造对象,甚至可以运行时修改类定义。

            何为反射?反射是指计算机程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。 上一段中提到了“自省”它与反射是有区别的,“自省”机制仅指程序在运行时对自身信息(元数据)的检测,而反射机制不仅包括要能在运行时对程序自身信息进行检测,还要求程序能进一步根据这些信息改变程序状态或结构。通过反射的运行时可以访问、检测和修改自身状态的特性,也就出现了动态代理。 

            反射最大的作用之一就在于我们可以不在编译时知道某个对象的类型,而在运行时通过提供完整的”包名+类名.class”得到。注意:不是在编译时,而是在运行时。

            反射的功能:1,在运行时能判断任意一个对象所属的类。2,在运行时能构造任意一个类的对象。3,在运行时判断任意一个类所具有的成员变量和方法。4,在运行时调用任意一个对象的方法。通俗的说就是,利用 Java 反射机制我们可以加载一个运行时才得知名称的 class,获悉其构造方法,并生成其对象实体,能对其 fields 设值并唤起其 methods。

            反射的应用场景:反射技术常用在各类通用框架开发中。因为为了保证框架的通用性,需要根据配置文件加载不同的对象或类,并调用不同的方法,这个时候就会用到反射——运行时动态加载需要加载的对象。

            反射的特点:由于反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射。另外,反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

    第二,动态代理

            动态代理是一种方便运行时动态构建代理,动态处理代理方法调用的机制,很多场景都是利用类似机制做到的,比如用来包装 RPC 调用,面向切面编程(AOP)。

            实现动态代理的方式很多,比如 JDK 自身提供的动态代理,就是主要利用了上面提到的反射机制。还有其他的实现方式,比如利用传说中更高性能的字节码操作机制,类似 ASM,cglib (基于ASM),javassist 等。比如,常可采用的 JDK 提供的动态代理接口 InvocationHandler 来实现动态代理类。其中 invoke 方法是该接口定义必须实现的,它完成对真实方法的调用。通过 InvocationHandler 接口,所有方法都由该 Handler 来进行处理,即所有被代理的方法都由InvocationHandler 接管实际的处理任务。此外,我们常可以在 invoke 方法实现中增加自定义的逻辑实现,实现对被代理类的业务逻辑无侵入。

            动态代理,首先,它是一个代理机制。代理可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成的。很多代理场景也可以看作是装饰器(Decorator)模式的应用。通过代理可以让调用者与实现者之间解耦。比如进行 RPC 调用,框架内部寻址,序列化,反序列化等,对于调用者往往没有太大意义的,通过代理,可以提供更加友善的界面。

            动态代理为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在两者之间起到中介的作用(可类比房屋中介,房东委托中介销售房屋、签订合同等)。

            所谓动态代理,就是编译阶段不用关心代理谁,而是在运行阶段才指定代理哪个一个对象(不确定性)。如果是自己写代理类的方式就是静态代理(确定性)。

            动态代理模式主要涉及三个要素:其一:抽象类接口。其二:被代理类(具体实现抽象接口的类)。其三:动态代理类:实际调用被代理类的方法和属性的类。

            应用场景:在一个程序中有两个类A、B,整个程序的运行都由 B 类来承担,A 类的所要做的工作是满足B的要求,如果在没有反射这种机制的条件下实现这个程序就会,既要把 B 类中的对整个程序运行逻辑进行编写,还要回到 A 类中对 B 的工作进行人工手动辅助,这时只要 B 的任何改动都会影响到 A 。 若在有了反射或代理之后 A 的代码就可以自己去访问、检测 B ,从而自动的修改 A 自身的状态来辅助 B。 

    相关文章

      网友评论

          本文标题:浅谈 java 反射和动态代理

          本文链接:https://www.haomeiwen.com/subject/hdffrqtx.html