java反射机制与动态代理
在学习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反射机制与动态代理的更多相关文章
- Java反射机制以及动态代理
Java反射机制以及动态代理 Java反射机制 含义与功能 Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类 ...
- Java反射机制可以动态修改实例中final修饰的成员变量吗?
问题:Java反射机制可以动态修改实例中final修饰的成员变量吗? 回答是分两种情况的. 1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了. ...
- 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】
方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; priva ...
- java.lang.Class<T> -- 反射机制及动态代理
Interface : Person package java_.lang_.component.bean; public interface Person { String area = " ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- Java的反射机制和动态代理
介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大的功能,可以原 ...
- java反射机制与动态加载类
什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...
- Java中的反射机制和动态代理
一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...
- java反射中的动态代理机制(有实例)
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
随机推荐
- sftp,get命令使用*通配符的方式获取批量的文件
需求描述: 今天在使用sftp进行get文件的时候,有很多文件名类似的文件,以为还是需要一个一个get 后来发现get也可以使用通配符的方式进行匹配获取多个文件,在此记录下 操作过程: 1.通过sft ...
- mongodb启动时报错ERROR: child process failed, exited with error number 1
不多说,直接上干货! 前期博客 Ubuntu14.04下Mongodb安装部署步骤(图文详解) Ubuntu16.04下Mongodb安装部署步骤(图文详解) root@zhouls-virtual- ...
- iis部署网站,使用虚拟路劲
此前一直使用vs2010,没有考虑过配置IIS,但是一个项目完成后交付给甲方使用.肯定是要考虑IIS的安装和部署的.现从IIS的安装和asp.NET项目的部署两个方面讲解. IIS安装: 网上很多教程 ...
- Animy.js,自己编写的功能丰富的html动画库
近期由于项目须要.本人制作了一款js的动画插件.能够用于完毕各种js动画.比方移动.拉升.变色等等,全部动画经常使用的功能都已经实现,比方播放.暂停.停止.循环.加速.减速.反向播放.缓动.路径动画. ...
- Python 常见文件操作的函数示例(转)
转自:http://www.cnblogs.com/txw1958/archive/2012/03/08/2385540.html # -*-coding:utf8 -*- ''''' Python常 ...
- YARN应用程序开发和设计流程
从业务的角度看,一个应用需要分两部分进行开发,一个是接入YARN平台,实现3个协议,通过YARN实现对集群资源的访问和利用:另一个是业务功能的实现,这个与YARN本身没有太大关系.下面主要阐述如何将一 ...
- Hash表 hash table 又名散列表
直接进去主题好了. 什么是哈希表? 哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构.也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度.这个映射函 ...
- Does the parameter type of the setter match the return type of the getter?
JDK 1.8, dubbo-admin版本是2.5.4-SNAPSHOT,tomcat8.5启动,报错: ERROR context.ContextLoader - Context initiali ...
- Go基础---->go的基础学习(一)
这里面记录一些学习go的基础知识.我希望爱我的人不寂寞,我希望我爱的人喜欢我 go的基础知识 一.go中的map的使用 package main import ( "fmt" ) ...
- 使用Android Studio调试内存问题
http://blog.csdn.net/yutao52shi/article/details/50055669 前言 内存问题对于Android开发者是永远的痛.如果一个android程序员说他没有 ...