浅谈Java反射机制(一)

Reflection,这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。 --来自百度百科定义

马上就要开始跟项目了,为了作些准备,了解了一下反射技术,今天想就自己对反射机制的了解作一些总结。

首先学习的是比较浅显的,通过传进来的对象去初始化一些变量,而这些变量是组成一个方法的必要条件,通过这些条件来调用指定的方法。界定一个唯一方法的因素有:
1,方法所属的类;
2,方法的名字;
3,方法的参数列表和顺序;
满足这三个条件,我们就可以通过java.lang.reflect.Method类,去创建一个Method类的对象method,通过method.invoke(affectedObject,params)来执行一个方法。

假定,我们现在是做远程的socket,通过流来传对象,对象皆为封装对象,即封装了需要用到的属性,类名、方法名、参数类型列表,参数列表:
[java] view plaincopyprint?package com.insigma.model; 
 
import java.io.Serializable; 
 
public class Call implements Serializable{ 
    private String className; 
    private String methodName; 
    private Class[] paramTypes; 
    private Object[] params; 
    private Object result; 
    public Call(){ 
         
    } 
    public Call(String className, String methodName,Class[] paramTypes, Object[] params){ 
        this.className = className; 
        this.methodName = methodName; 
        this.paramTypes = paramTypes; 
        this.params = params; 
    } 
     
    public String getClassName(){ 
        return className; 
    } 
    public String getMethodName(){ 
        return methodName; 
    } 
    public Class[] getParamTypes(){ 
        return paramTypes; 
    } 
    public Object[] getParams(){ 
        return params; 
    } 
    public Object getResult(){ 
        return result; 
    } 
    public void setResult(Object result){ 
        this.result = result; 
    } 


package com.insigma.model;

import java.io.Serializable;

public class Call implements Serializable{
private String className;
private String methodName;
private Class[] paramTypes;
private Object[] params;
private Object result;
public Call(){

}
public Call(String className, String methodName,Class[] paramTypes, Object[] params){
this.className = className;
this.methodName = methodName;
this.paramTypes = paramTypes;
this.params = params;
}

public String getClassName(){
return className;
}
public String getMethodName(){
return methodName;
}
public Class[] getParamTypes(){
return paramTypes;
}
public Object[] getParams(){
return params;
}
public Object getResult(){
return result;
}
public void setResult(Object result){
this.result = result;
}
}
因为要通过流来传输对象,最好把这对象实现可序列化接口Serializable。通过构造器来为封装的属性赋值。

接下来就是ServerSocket,在这里监听远程socket那边是否有对象传过来,以作反应:
[java] view plaincopyprint?package com.insigma.model; 
 
import java.io.*; 
import java.net.*; 
import java.util.*; 
import java.lang.reflect.*; 
 
public class SimpleServer { 
     
    private Map remoteObjects=new HashMap();    
    //存放远程对象的缓存  
    /** 把一个远程对象放到缓存中 */ 
    public void register(String className,Object remoteObject){ 
        remoteObjects.put( className,remoteObject);  
    } 
     
    public void service()throws Exception{ 
        ServerSocket serverSocket = new ServerSocket(8000); 
        System.out.println("服务器启动."); 
         
        while(true){ 
             
            Socket socket=serverSocket.accept(); 
            InputStream in=socket.getInputStream(); 
            ObjectInputStream ois=new ObjectInputStream(in); 
             
            OutputStream out=socket.getOutputStream(); 
            ObjectOutputStream oos=new ObjectOutputStream(out); 
             
            Call call=(Call)ois.readObject(); 
            //接收客户发送的Call对象  
            System.out.println(call); 
            call=invoke(call);       
             
            //调用相关对象的方法  
            oos.writeObject(call);    
             
            //向客户发送包含了执行结果的Call对象  
            ois.close();oos.close(); 
            socket.close(); 
             
        } 
         
    } 
    public Call invoke(Call call){ 
        Object result=null; 
        try{ 
             
            String className=call.getClassName(); 
            String methodName=call.getMethodName(); 
            Object[] params=call.getParams(); 
            Class classType=Class.forName(className); 
            Class[] paramTypes=call.getParamTypes(); 
            Method method=classType.getMethod(methodName, paramTypes);   
            Object remoteObject=remoteObjects.get(className); 
             
            //从缓存中取出相关的远程对象  
            if(remoteObject==null){ 
                throw new Exception(className+"的远程对象不存在"); 
            }else{ 
                result=method.invoke(remoteObject,params); 
                } 
        }catch(Exception e){ 
            result=e; 
        } 
         
        call.setResult(result);         
        //设置方法执行结果  
        return call; 
    } 
    public static void main(String args[])throws Exception { 
         
        SimpleServer server=new SimpleServer(); 
         
        //把事先创建的HelloServiceImpl对象加入到服务器的缓存中  
        server.register("com.insigma.model.HelloService",new HelloServiceImpl()); 
        server.service(); 
         
    }  
     


package com.insigma.model;

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;

public class SimpleServer {

private Map remoteObjects=new HashMap();  
//存放远程对象的缓存
/** 把一个远程对象放到缓存中 */
public void register(String className,Object remoteObject){
remoteObjects.put( className,remoteObject);
}

public void service()throws Exception{
ServerSocket serverSocket = new ServerSocket(8000);
System.out.println("服务器启动.");

while(true){

Socket socket=serverSocket.accept();
InputStream in=socket.getInputStream();
ObjectInputStream ois=new ObjectInputStream(in);

OutputStream out=socket.getOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(out);

Call call=(Call)ois.readObject();
//接收客户发送的Call对象
System.out.println(call);
call=invoke(call);     

//调用相关对象的方法
oos.writeObject(call);  

//向客户发送包含了执行结果的Call对象
ois.close();oos.close();
socket.close();

}

}
public Call invoke(Call call){
Object result=null;
try{

String className=call.getClassName();
String methodName=call.getMethodName();
Object[] params=call.getParams();
Class classType=Class.forName(className);
Class[] paramTypes=call.getParamTypes();
Method method=classType.getMethod(methodName, paramTypes); 
Object remoteObject=remoteObjects.get(className);

//从缓存中取出相关的远程对象
if(remoteObject==null){
throw new Exception(className+"的远程对象不存在");
}else{
result=method.invoke(remoteObject,params);
}
}catch(Exception e){
result=e;
}

call.setResult(result);       
//设置方法执行结果
return call;
}
public static void main(String args[])throws Exception {

SimpleServer server=new SimpleServer();

//把事先创建的HelloServiceImpl对象加入到服务器的缓存中
server.register("com.insigma.model.HelloService",new HelloServiceImpl());
server.service();

}

}
这里,需要注册类型,没有注册的类型,远程传过来的时候,会出现异常,这里大概是出于安全考虑。
下来就是Socket的客户端了
[java] view plaincopyprint?package com.insigma.model; 
 
import java.io.*; 
import java.net.*; 
 
public class SimpleClient { 
     
    public void invoke()throws Exception{ 
         
        Socket socket = new Socket("localhost",8000); 
        OutputStream out=socket.getOutputStream(); 
         
        ObjectOutputStream oos=new ObjectOutputStream(out); 
        InputStream in=socket.getInputStream(); 
        ObjectInputStream ois=new ObjectInputStream(in); 
        Call call=new Call("com.insigma.model.HelloService","getTime",new Class[]{},new Object[]{}); 
        //Call call=new Call("com.insigma.model.HelloService","echo",new Class[]{String.class},new Object[]{"Hello"});    
        oos.writeObject(call); 
        //向服务器发送Call对象  
        call=(Call)ois.readObject();        
        //接收包含了方法执行结果的Call对象  
        System.out.println(call.getResult()); 
        ois.close(); 
        oos.close(); 
        socket.close(); 
     
    } 
    public static void main(String args[])throws Exception { 
        new SimpleClient().invoke();  
         
    } 


package com.insigma.model;

import java.io.*;
import java.net.*;

public class SimpleClient {

public void invoke()throws Exception{

Socket socket = new Socket("localhost",8000);
OutputStream out=socket.getOutputStream();

ObjectOutputStream oos=new ObjectOutputStream(out);
InputStream in=socket.getInputStream();
ObjectInputStream ois=new ObjectInputStream(in);
Call call=new Call("com.insigma.model.HelloService","getTime",new Class[]{},new Object[]{});
//Call call=new Call("com.insigma.model.HelloService","echo",new Class[]{String.class},new Object[]{"Hello"}); 
oos.writeObject(call);
//向服务器发送Call对象
call=(Call)ois.readObject();      
//接收包含了方法执行结果的Call对象
System.out.println(call.getResult());
ois.close();
oos.close();
socket.close();

}
public static void main(String args[])throws Exception {
new SimpleClient().invoke();

}
}
当然咯,被反射的类也是必须贴上,不然给出一份不能运行的代码,肯定要被唾液淹死。对被反射的类,做了一个接口来解耦。
[java] view plaincopyprint?package com.insigma.model; 
 
 
public interface HelloService { 
    public String echo(String words); 
    public String getTime(); 


package com.insigma.model;


public interface HelloService {
public String echo(String words);
public String getTime();
}

这里是实现类,只提供很简单的测试功能。
[java] view plaincopyprint?package com.insigma.model; 
 
import java.util.Date; 
 
public class HelloServiceImpl implements HelloService{ 
 
    @Override 
    public String echo(String words) { 
         
        return "echo:" + words; 
    } 
 
    @Override 
    public String getTime() { 
         
        return new Date().toString(); 
    } 
     


package com.insigma.model;

import java.util.Date;

public class HelloServiceImpl implements HelloService{

@Override
public String echo(String words) {

return "echo:" + words;
}

@Override
public String getTime() {

return new Date().toString();
}

}
先运行服务端,再运行客户端,这小小的测试,也算完成了。


猜你喜欢

转载自20120923lina.iteye.com/blog/1692019