在学习HadoopRPC时。用到了函数调用。函数调用都是採用的java的反射机制和动态代理来实现的,所以如今回想下java的反射和动态代理的相关知识。

一、反射

JAVA反射机制定义: JAVA反射机制是java程序在执行状态中。对于随意一个类,都能够知道这个类的所有属性和方法;对于随意一个对象,都能够调用它的随意一个方法;这样的动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 

反射就是把Java类中的各种成分映射成对应的Java类。

Java反射机制主要提供了下面功能: 

1、在执行时推断随意一个对象所属的类。
2、在执行时构造随意一个类的对象;
3、在执行时推断随意一个类所具有的成员变量和方法;
4、在执行时调用随意一个对象的方法;
5、生成动态代理。

我们了解了反射机制的功能,那么我们怎样详细来实现它呢?

 一个类中的每一个成员都能够用对应的反射包中的一个类的实例对象来表示,通过Class类的方法能够得到这些实例对象。这个“成员”就包括:类的构造函数、成员变量、方法等一些信息。而他们所对应的反射包中的类各自是:Constructor类、Field类、Method类。

这里仅仅要讲讲动态代理的知识。

二、动态代理

  Java动态代理类位于Java.lang.reflect包下,一般主要涉及到下面两个类:
    (1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时。第一个參数obj通常是指代理类。method是被代理的方法,如上例中的request()。args为该方法的參数数组。

这个抽象方法在代理类中动态实现。 

    (2).Proxy:该类即为动态代理类。作用相似于上例中的ProxySubject,当中主要包括下面内容: 

      Protected Proxy(InvocationHandler h):构造函数。预计用于给内部的h赋值。 

      Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类。当中loader是类装载器,interfaces是真实类所拥有的所有接口的数组。 

      Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类能够当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。

 实例:

1、定义一个HelloWorld接口

 /**
* 定义一个HelloWorld接口
*
* @author
*
*/
public interface HelloWorld {
public void sayHelloWorld();
}

2、类HelloWorldImpl是HelloWorld接口的实现

 /**
* 类HelloWorldImpl是HelloWorld接口的实现
*
* @author
*
*/
public class HelloWorldImpl implements HelloWorld{ public void sayHelloWorld() {
System.out.println("HelloWorld!");
} }

3、HelloWorldHandler是 InvocationHandler接口实现

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; /**
* 实如今方法调用前后向控制台输出两句字符串
*
* @author
*
*/
public class HelloWorldHandler implements InvocationHandler{
//要代理的原始对象
private Object obj; public HelloWorldHandler(Object obj) {
super();
this.obj = obj;
} /**
* 在代理实例上处理方法调用并返回结果
*
* @param proxy 代理类
* @param method 被代理的方法
* @param args 该方法的參数数组
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
//调用之前
doBefore();
//调用原始对象的方法
result=method.invoke(obj, args);
//调用之后
doAfter();
return result;
} private void doBefore(){
System.out.println("before method invoke");
} private void doAfter(){
System.out.println("after method invoke");
} }

4、測试类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; public class HelloWorldTest { public static void main(String[] args) {
HelloWorld helloWorld=new HelloWorldImpl();
InvocationHandler handler=new HelloWorldHandler(helloWorld); //创建动态代理对象
HelloWorld proxy=(HelloWorld)Proxy.newProxyInstance(
helloWorld.getClass().getClassLoader(),
helloWorld.getClass().getInterfaces(),
handler);
proxy.sayHelloWorld();
}
}

执行结果为:

before method invoke

HelloWorld

after method invoke

总结:

一个典型的动态代理创建对象过程可分为下面四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);

2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});

3、通过反射机制获取动态代理类的构造函数,其參数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

4、通过构造函数创建代理类实例。此时需将调用处理器对象作为參数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));

为了简化对象创建过程。Proxy类中的newInstance方法封装了2~4。仅仅需两步就可以完毕代理对象的创建。

生成的ProxySubject继承Proxy类实现Subject接口。实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))

综合上面所说的,作为一个Dynamic Proxy,它必须满足下面三个条件:
        1、实现了InvocationHandler接口,实现接口中定义的invoke方法。
        2、包括接口实现类的实例;
        3、通过Proxy.newProxyInstance方法实现Proxy与接口之间的绑定
再来回想一下定义
 Dynamic Proxy是这样一种class:它是在执行时生成的class,在生成它时你必须提供一组interface给它。然后该class就宣称它实现了这些 interface。你当然能够把该class的实例当作这些interface中的不论什么一个来用。

当然啦,这个Dynamic Proxy事实上就是一个Proxy。它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作   。

java反射机制与动态代理的更多相关文章

  1. Java反射机制以及动态代理

    Java反射机制以及动态代理 Java反射机制 含义与功能 Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类 ...

  2. Java反射机制可以动态修改实例中final修饰的成员变量吗?

    问题:Java反射机制可以动态修改实例中final修饰的成员变量吗? 回答是分两种情况的. 1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了. ...

  3. 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】

    方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...

  4. java.lang.Class<T> -- 反射机制及动态代理

    Interface : Person package java_.lang_.component.bean; public interface Person { String area = " ...

  5. 【Java基础】java中的反射机制与动态代理

    一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...

  6. Java的反射机制和动态代理

    介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原 ...

  7. java反射机制与动态加载类

    什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...

  8. Java中的反射机制和动态代理

    一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...

  9. java反射中的动态代理机制(有实例)

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

随机推荐

  1. linux nfs

    linux(十四)之linux NFS服务管理 学到这里差不多就结束了linux的基础学习了,其实linux的内容并不难,我们要经常的反复的去操作它,多多和它去联络感情才能很好的掌握这个linux. ...

  2. Jmeter在命令行运行技巧

    For non-interactive testing, you may choose to run JMeter without the GUI. To do so, use the followi ...

  3. FairyGUI学习

    官网:http://www.fairygui.com/ 教程:http://www.taikr.com/course/446/tasks 博客:http://gad.qq.com/article/de ...

  4. phpcms v9如何更改分页显示条数?

    默认显示页码数有10条,比如想更改成显示3条,例如这样 上一页 1 2 3...34 下一页 更改phpcms\libs\functions\global.func.php,找到分页函数,大概在665 ...

  5. go在线图书

    https://books.studygolang.com/The-Golang-Standard-Library-by-Example/

  6. 【ExtJs】 ExtJs4.2 基本表单组件的使用

    包含ExtJs 基本的组件radioGroup,ComboBox,File,NumberField... <%-- Created by IntelliJ IDEA. User: Adminis ...

  7. 超全面的JavaWeb笔记day04<dom树等>

    1.案例:在末尾添加节点(*****) 创建标签 createElement方法 创建文本 createTextNode方法 把文本添加到标签下面 appendChild方法 2.元素对象(了解) 如 ...

  8. Swift - UITableView的用法

    因为倾向于纯代码编码,所以不太喜欢可视化编程,不过也略有研究,所以项目里面的所有界面效果,全部都是纯代码编写! 终于到了重中之重的tableview的学习了,自我学习ios编程以来,工作中用得最多的就 ...

  9. Swift-基础语法之变量&常量&元组

    使用 let来声明一个常量,用 var来声明一个变量.常量的值在编译时并不要求已知,但是你必须为其赋值一次.这意味着你可以使用常量来给一个值命名,然后一次定义多次使用 myVariable = let ...

  10. m2014-android->安卓开发在线案例

    1.www.javaapk.com account: 克里斯  pwd: xiaobai 这个网站非常不错,各种例子,各种可供下载演示的项目,用了就知道,好处不多说,真心赞!