您的位置:首页 > 其它

RPC中用到的 *动态代理,反射机制,NIO

2015-09-17 19:27 260 查看
今天在学习RPC协议时,用到了动态代理和反射机制

所以,我们先来看看动态机制:在java的动态代理中,有两个重要的类或接口,一个是InvocationHandler(Interface),另一个则是Proxy(Class0,这一个类和接口。首先我们来看看java的api对这两个类的描述



InvocationHandler:

InvocationHandler is the interface implemented by the invocation handler of a proxy instance.

Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.

每一个动态代理类都必须要实现InvocationHadler这个接口,并且每个代理类实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。

我们来看看这个唯一的方法invoke

Object invoke(Object proxy,Method method,Object[] args)throws Throwable

这三个参数所代表的含义在我看来分别是:

proxy:指我们要代理的那个真实的对象

method:指代的是我们所要调用真是对象的某个方法的Method对象

args:指代的是调用真实对象某个方法时接受的参数。

然后,我们来看看Proxy这个类

Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.

这个方法的作用就是得到一个动态代理的对象,

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

她也有三个参数,这三个参数的意思为:

loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代码对象进行加载

interfance:一个Interface对象的数组,表示的是我将要给我所需要代理对象提供一组什么接口,如果我提供了一组接口给他,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了。

h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。

一个关于动态代理的小实例:

之前在网上看了很多,发现都是错的,在此附上自己写的

(1)我们定义一个接口:真实的对象

(2)实现接口

(3)代理类:实现InvocationHanlder接口:注意,这里我们要用到反射机制,让他去调用自身的类,使用网上的Subject在做客户端测试时,是找不到方法的

(4)客户端测试

下面附上源代码

public interface RealProxy {

public void call();

}

public class RealProxyImpl implements RealProxy{

@Override

public void call() {

// TODO Auto-generated method stub

System.out.println("被代理类");

}

}

public class DLproxy implements InvocationHandler{

//先定义一个对象

private Object sum;

public DLproxy(){}

public DLproxy(Object obj ){

sum=obj;

}

//之前并没有写这个方法,发现是不对的,但是一直想不通,为什么不能直接在客户端进行代用,之后发现,有可能是subject方法的没法调用

public Object createProxy(Object sum){

this.sum=sum;

return Proxy.newProxyInstance(this.sum.getClass().getClassLoader(), this.sum.getClass().getInterfaces(), this);

}

@Override

public Object invoke(Object object, Method method, Object[] args)

throws Throwable {

// TODO Auto-generated method stub

RealProxyImpl ps=(RealProxyImpl) this.sum;

System.out.println("call before"+method);

//invoke(proxy, method, args);

System.out.println("call after"+method);

return method.invoke(sum, args);

}

}

public class TextProxy {

public static void main(String[] args) {

DLproxy pro=new DLproxy();

RealProxyImpl ps=new RealProxyImpl();

RealProxy ps1=(RealProxy) pro.createProxy(ps);

ps1.call();

// RealProxy rp=new RealProxyImpl();

// Subject subject=(Subject) Proxy.newProxyInstance(rp.getClass().getClassLoader(), rp.getClass().getInterfaces(), (InvocationHandler) rp);

}

}

反射机制

其实理解Java的反射和理解JavaScript的eval函数一样,都是将一个字符型数据转换为相应的类、属性和方法

官方说法为:

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

在我看来,反射,就是我们可以任意的去调用一个类的所有方法。

附上代码

/**

* 反射机制的实现

* @author root

*

*/

public class User {

private String name;

private int age;

public User() {

name = "无名氏";

age = 22;

}

public User(String name) {

this.name = name;

this.age = 22;

}

public String toString() {

return "名字是:" + name;

}

public String toString(int age, String name) {

this.name = name;

this.age = age;

return "名字是:" + name + ";年龄是:" + age;

}

public static void main(String[] args) {

/**

* 我们之前的方法

*/

User accpTeacher = new User();

System.out.println(accpTeacher);

/**

* // 实例化一个类

*

* 首先Class.forName(类名)是将这个类加载到JVM虚拟机中,

* 获得一个类型为Class的类,然后调用其newInstance()方法,相当于实例化(调用无参的构造函数);

* 所以以上两段代码的运行效果是一致的。

*/

try {

Object
user = Class.forName(User.class.getName()).newInstance();

System.out.println(user);

} catch (InstantiationException | IllegalAccessException

| ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

/**

* 通过构造方法实例化一个类,本例是一个有参数的构造函数,并且构造函数可以为private修饰

*/

Class[] argtype=new Class[]{String.class};//代表构造方法的参数

Object[] argparam=new Object[]{"张三"};//代表构造方法的参数值

try {

Class classtype=Class.forName(User.class.getName());

//获得构造方法,argtype是参数类型数组,我们这里代表的是参数只有一个string类型

Constructor constructor=classtype.getDeclaredConstructor(argtype);

//访问私有构造函数,Spring可哟配置私有的属性和方法,其实就是用到这里

constructor.setAccessible(true);

Object user2=constructor.newInstance(argparam);

System.out.println(user2);

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (NoSuchMethodException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SecurityException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InstantiationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IllegalArgumentException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InvocationTargetException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

NIO的实现

概念引用:

NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有事件发生时,他会通知我们,传回一组SelectionKey,我们读取这些Key,就会获得我们刚刚注册过的socketchannel,然后,我们从这个Channel中读取数据,放心,包准能够读到,接着我们可以处理这些数据。

Selector内部原理实际是在做一个对所注册的channel的轮询访问,不断的轮询(目前就这一个算法),一旦轮询到一个channel有所注册的事情发生,比如数据来了,他就会站起来报告,交出一把钥匙,让我们通过这把钥匙来读取这个channel的内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: