欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java常见应用-反射,RPC

程序员文章站 2024-03-26 13:24:23
...

Java常见应用-反射,RPC

一.反射

简介:反射机制是在【运行状态】中:

对于任意一个类,都能够知道这个类的所有属性和方法;

对于任意一个对象,都能够调用它的任意一个方法和属性。

反射提供的功能

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;
  • 生成动态代理。

三种获取反射入口的方法

package com.nike.app.reflect;

public interface MyInterFaceA {
    void interFaceAMethod01();
}
package com.nike.app.reflect;

public interface MyInterFaceB {

    void interFaceBMethod01();
}
package com.nike.app.reflect;

public class Person implements MyInterFaceA,MyInterFaceB {
    private int id;
    private String name;
    private int age;
    public String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person() {}

    public Person(int id) {
        this.id = id;
    }

     Person(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public Person(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }


    public Person(int id, String name, int age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public static void staticMethod(){
        System.out.println("Static Method()...");
    }

    private void privateMethod(){
        System.out.println("Private Method()...");
    }

    private void privateMethod(int a1,String a2){
        System.out.println("Private Method("+a1+","+a2+")...");
    }

    @Override
    public void interFaceAMethod01() {
        System.out.println("InterFaceA Method01()...");
    }

    @Override
    public void interFaceBMethod01() {
        System.out.println("InterFaceB Method01()...");
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

package com.nike.app.reflect;

public class ReflectDemo01 {
    /**
     * 通过反射获取类,操作类
     * @param args
     */
    public static void main(String[] args) {
        //获取反射对象(反射入口):Class
        //1 Class.forName("全类类(包名+类名)");
        //2 Class_Name.class;
        //3 Class_Instance.getClass();

        //1 Class.forName("类的全路径")
        try {
            Class<?> personClass01 = Class.forName("com.nike.app.reflect.Person");
            System.out.println(personClass01);
            //class com.nike.app.reflect.Person
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //2 class_name.class
        Class<Person> personClass02 = Person.class;
        System.out.println(personClass02);
        //class com.nike.app.reflect.Person

        //3 class_instance.getClass()
        Person person = new Person();
        Class<? extends Person> personClass03 = person.getClass();
        System.out.println(personClass03);
        //class com.nike.app.reflect.Person
    }
}

通过反射获取类的信息

package com.nike.app.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectDemo02 {

    //获取方法
    public static void demo01() {
        //获取反射入口,推荐使用 Class.forName
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //获取类的方法
        //1.获取所有的公共方法(不只是当前类的public方法,也包括其父类,父接口中的public方法,且符合访问修饰符规律)
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }

        //输出结果为:
        /*
        public java.lang.String com.nike.app.reflect.Person.getAddress()
        public java.lang.String com.nike.app.reflect.Person.getName()
        public int com.nike.app.reflect.Person.getId()
        public void com.nike.app.reflect.Person.setName(java.lang.String)
        public void com.nike.app.reflect.Person.setId(int)
        public int com.nike.app.reflect.Person.getAge()
        public void com.nike.app.reflect.Person.setAge(int)
        public static void com.nike.app.reflect.Person.staticMethod()
        public void com.nike.app.reflect.Person.setAddress(java.lang.String)
        public void com.nike.app.reflect.Person.interFaceAMethod01()
        public void com.nike.app.reflect.Person.interFaceBMethod01()
        public final void java.lang.Object.wait() throws java.lang.InterruptedException
        public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
        public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
        public boolean java.lang.Object.equals(java.lang.Object)
        public java.lang.String java.lang.Object.toString()
        public native int java.lang.Object.hashCode()
        public final native java.lang.Class java.lang.Object.getClass()
        public final native void java.lang.Object.notify()
        public final native void java.lang.Object.notifyAll()
         */
    }

    //获取所有的父接口
    public static void demo02() {
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //多实现
        Class<?>[] interfaces = personClass.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface);
        }
        //输出结果为:
        /*
        interface com.nike.app.reflect.MyInterFaceA
        interface com.nike.app.reflect.MyInterFaceB
         */
    }

    //获取所有的父类
    public static void demo03(){
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //单继承
        Class<?> superclass = personClass.getSuperclass();
        System.out.println(superclass);

        //输出结果:
        //class java.lang.Object
    }

    //获取所有的构造方法
    public static void demo04(){
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Constructor<?>[] constructors = personClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }

        //输出结果为:
        /*
        public com.nike.app.reflect.Person(int)
        public com.nike.app.reflect.Person(int,java.lang.String,int)
        public com.nike.app.reflect.Person(int,java.lang.String,int,java.lang.String)
        public com.nike.app.reflect.Person()
         */


    }

    //获取所有公共的属性
    public static void demo05(){
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //输出结果为:
        /*
        public java.lang.String com.nike.app.reflect.Person.address
         */
    }

    //获取当前类中的所有方法(1.只能时当前类,2.忽略访问修饰符限制)
    public static void demo06(){
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Method[] declaredMethods = personClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method);
        }
        //输出结果为:
        /*
        public java.lang.String com.nike.app.reflect.Person.getAddress()
        public java.lang.String com.nike.app.reflect.Person.getName()
        public int com.nike.app.reflect.Person.getId()
        public void com.nike.app.reflect.Person.setName(java.lang.String)
        private void com.nike.app.reflect.Person.privateMethod()
        public void com.nike.app.reflect.Person.setAge(int)
        public void com.nike.app.reflect.Person.setId(int)
        public static void com.nike.app.reflect.Person.staticMethod()
        public int com.nike.app.reflect.Person.getAge()
        public void com.nike.app.reflect.Person.setAddress(java.lang.String)
        public void com.nike.app.reflect.Person.interFaceAMethod01()
        public void com.nike.app.reflect.Person.interFaceBMethod01()
         */
    }

    //获取当前类的所有属性
    public static void demo07(){
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        //输出结果为:
        /*
        private int com.nike.app.reflect.Person.id
        private java.lang.String com.nike.app.reflect.Person.name
        private int com.nike.app.reflect.Person.age
        public java.lang.String com.nike.app.reflect.Person.address
         */
    }

    //获取当前反射所代表类(接口)的所有对象
    public static void demo08() throws IllegalAccessException, InstantiationException {
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Person person = (Person)personClass.newInstance();
        person.interFaceAMethod01();
    }


    public static void main(String[] args) throws Exception {
        demo08();
    }
}

通过反射获取类实例并操作类实例

package com.nike.app.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 通过反射获取类实例对象并操作该类实例对象
 * @author NikeHu
 */
public class ReflectDemo03 {
    public static void main(String[] args) {
        demo02();

    }

    public static void demo01(){
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
            //获取类对象实例
            Person person = (Person) personClass.newInstance();
            person.setName("NikeHu");
            person.setAge(22);
            person.setId(9527);
            person.setAddress("西安市");
            System.out.println(person);
            //获取某一个属性
            Field id = personClass.getDeclaredField("id");
            //修改私有属性的访问权限,开启私有属性的访问权限
            id.setAccessible(true);
            id.set(person,1234);
            Field address = personClass.getDeclaredField("address");
            address.set(person,"吉安市");
            System.out.println(person);
            //修改私有方法的访问权限
            Method privateMethod = personClass.getDeclaredMethod("privateMethod", null);
            privateMethod.setAccessible(true);
            //通过反射调用私有方法
            privateMethod.invoke(person,null);
            //通过反射修改带参私有方法的访问权限,并调用该带参私有方法
            Method privateMethod1 = personClass.getDeclaredMethod("privateMethod", int.class, String.class);
            privateMethod1.setAccessible(true);
            privateMethod1.invoke(person,12,"Alex");


        } catch (Exception e) {
            e.printStackTrace();
        }
        //输出结果为:
        /*
        Person{id=9527, name='NikeHu', age=22, address='西安市'}
        Person{id=1234, name='NikeHu', age=22, address='吉安市'}
        Private Method()...
        Private Method(12,Alex)...
         */
    }

    //通过反射操作类的构造方法
    public static void demo02(){
        Class<?> personClass = null;
        try {
            personClass = Class.forName("com.nike.app.reflect.Person");
            //1.无参构造,可以不写参数或写null
            Constructor<?> constructor01 = personClass.getConstructor(null);
            Person person01 = (Person)constructor01.newInstance(null);
            //2.带参构造
            Constructor<?> constructor02 = personClass.getConstructor(int.class);
            Person person02 = (Person)constructor02.newInstance(9527);
            //3.私有构造
            Constructor<?> constructor03 = personClass.getDeclaredConstructor(String.class, String.class);
            //修改私有构造的访问权限
            constructor03.setAccessible(true);
            Person person03 = (Person)constructor03.newInstance("NikeHu", "南京市");
            System.out.println(person01);
            System.out.println(person02);
            System.out.println(person03);
            //输出结果为:
            /*
            Person{id=0, name='null', age=0, address='null'}
            Person{id=9527, name='null', age=0, address='null'}
            Person{id=0, name='NikeHu', age=0, address='南京市'}
            */

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

通过反射在运行中动态地创建类实例和调用类中的方法

在项目的根目录下创建class.txt文件

class.txt

classname=com.nike.app.reflect.Person
methodname=interFaceAMethod01
package com.nike.app.reflect;

public class Student {
    public String name;
    private int score;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public void  sayHi(){
        System.out.println("Hi,I am a Student!");
    }

    @Override
    public String toString() {
        return "Student{" +
                "Name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}
package com.nike.app.reflect;

import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 动态加载类名和类方法
 */
public class ReflectDemo04 {
    public static void main(String[] args) {
        Properties prop = new Properties();
        try {
            prop.load(new FileReader("class.txt"));
            String className = (String)prop.get("classname");
            String methodName = (String)prop.get("methodname");
            Class<?> mClass = Class.forName(className);
            Method method = mClass.getMethod(methodName);
            method.invoke(mClass.newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//InterFaceA Method01()...

修改class.txt文件

classname=com.nike.app.reflect.Student
methodname=sayHi

程序运行结果为:

Hi,I am a Student!

反射可以越过泛型检查

package com.nike.app.reflect;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * 反射可以越过泛型检查
 */
public class ReflectDemo05 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add(789);
        Class<?> listClass = list.getClass();
        try {
            Method add = listClass.getMethod("add", Object.class);
            add.invoke(list,"abc");
            add.invoke(list,new Person(9527,"NikeHu",22,"西安市"));
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //输出结果为:[123, 456, 789, abc, Person{id=9527, name='NikeHu', age=22, address='西安市'}]
    }
}

动态操作属性赋值

package com.nike.app.reflect.utils;

import com.nike.app.reflect.Person;
import com.nike.app.reflect.Student;

import java.lang.reflect.Field;

public class FieldUtils {
    public static void setProperty(Object obj,String fieldname,Object val){
        Class<?> aClass = obj.getClass();
        try {
            Field field = aClass.getDeclaredField(fieldname);
            field.setAccessible(true);
            field.set(obj,val);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Person person = new Person();
        setProperty(person,"name","NikeHu");
        setProperty(person,"address","西安市");
        System.out.println(person);
        //Person{id=0, name='NikeHu', age=0, address='西安市'}

        Student student = new Student();
        setProperty(student,"name","nike");
        setProperty(student,"score",98);
        System.out.println(student);
        //Student{Name='nike', score=98}
    }
}

二.RPC

RPC(Remote Procudure Call):远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。

Java常见应用-反射,RPC

HelloService.java

package com.nike.app.rpc;

public interface HelloService {
    String sayHello(String name);
}

HelloServiceImpl.java

package com.nike.app.rpc;

public class HelloServiceImpl implements HelloService{
    @Override
    public String sayHello(String name) {
        return ("Hello,"+name+"!");
    }
}

ServerCenter.java

package com.nike.app.rpc;

/**
 * 服务中心
 */
public interface ServiceCenter {

    /**
     * 开启服务
     */
    void start();

    void close();

    /**
     * 注册服务
     */
    void register(Class service,Class serviceImpl);
}

ServerCenterImpl.java

package com.nike.app.rpc;

import java.io.*;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServiceCenterImpl implements ServiceCenter{
    /**
     * serviceRegister:服务端所有可供客户端访问的接口,都注册到该map中
     * key:接口名,“HelloService”
     * value:接口真正的实现。
     */
    private static Map<String,Class> serviceRegister = new HashMap();
    private static int port;
    //连接池:连接池中存在多个连接对象,每个连接对象都可以处理一个客户端请求
    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private boolean isRunning;
    public ServiceCenterImpl(int port){
        ServiceCenterImpl.port = port;
    }

    @Override
    public void start() {
        ServerSocket server = null;
        try {
            server = new ServerSocket();
            server.bind(new InetSocketAddress(port));
        } catch (IOException e) {
            e.printStackTrace();
        }
        isRunning = true;
        while(true){
            System.out.println("start server...");
            //等待客户端连接
            try {
                Socket socket = server.accept();
                executor.execute(new ServiceTask(socket));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void close() {
        isRunning = false;
        executor.shutdown();
    }

    @Override
    public void register(Class service,Class serviceImpl) {
        serviceRegister.put(service.getName(),serviceImpl);
    }

    private static class ServiceTask implements Runnable{
        Socket socket;
        public ServiceTask(){ }
        public ServiceTask(Socket socket){
            this.socket = socket;
        }
        @Override
        public void run() {
            ObjectInputStream input = null;
            ObjectOutputStream output = null;
            try {
                //接受客户端连接及请求
                input = new ObjectInputStream(socket.getInputStream());
                String serviceName = input.readUTF();
                String methodName = input.readUTF();
                Class<?>[] paramTypes = (Class<?>[]) input.readObject();
                Object[] args = (Object[]) input.readObject();
                //处理客户端请求
                Class serviceClass = serviceRegister.get(serviceName);
                Method method = serviceClass.getDeclaredMethod(methodName, paramTypes);
                //执行该方法
                Object result = method.invoke(serviceClass.newInstance(), args);
                //向客户端返回结果
                output = new ObjectOutputStream(socket.getOutputStream());
                output.writeObject(result);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (input != null){
                        input.close();
                    }
                    if (output != null){
                        output.close();
                    }
                    if (socket != null){
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }

        }
    }
}

Client.java

package com.nike.app.rpc;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;

public class Client {
    //获取代表服务端接口的动态代理对象

    /**
     *
     * @param serviceInter 请求的接口名
     * @param addr 服务器ip和端口
     * @param <T>
     * @return
     */
    public static <T> T getRemoteProxyObj(Class serviceInter, InetSocketAddress addr){
        return (T) Proxy.newProxyInstance(serviceInter.getClassLoader(), new Class<?>[]{serviceInter}, new InvocationHandler() {
            /**
             *
             * @param proxy 代理的对象
             * @param method 代理的对象的方法
             * @param args 参数列表
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Socket socket = new Socket();
                socket.connect(addr);
                ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                //发送:序列化流(对象流)
                //发送接口名,方法名
                output.writeUTF(serviceInter.getName());
                output.writeUTF(method.getName());
                //方法参数,方法参数类型
                output.writeObject(method.getParameterTypes());
                output.writeObject(args);
                //等待服务端处理...
                //接收客户端处理后的返回值
                ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                Object res = input.readObject();
                if (input != null){ input.close(); };
                if (output != null){ output.close(); };
                if (socket != null){ socket.close(); };
                return res;
            }
        });
    }

}

RPCServer.java

package com.nike.app.rpc;

public class RPCServer {
    public static void main(String[] args) {
        ServiceCenter center = new ServiceCenterImpl(9999);
        //注册服务
        center.register(HelloService.class,HelloServiceImpl.class);
        //启动服务
        center.start();
    }
}

RPCClient.java

package com.nike.app.rpc;

import java.net.InetSocketAddress;

public class RPCClient {
    public static void main(String[] args) throws ClassNotFoundException {
        HelloService service = Client.getRemoteProxyObj(Class.forName("com.nike.app.rpc.HelloService"),new InetSocketAddress("127.0.0.1",9999));
        System.out.println(service.sayHello("NikeHu"));
    }
}

RPC原理总结

1.客户端通过Socket请求服务端,并且通过字符串形式将需要请求的接口发送给服务端;

2.服务端将可以提供的接口注册到服务中心(通过Map保存,key:接口名,value:接口实现类);

3.服务端接收到请求后,通过请求的接口名,在服务中心的map中寻找对应的接口实现类;解析客户端的接口名,方法名,通过反射执行该方法,执行完毕后,将该方法的返回值返回客户端。

相关标签: Java高级