javaSE-day14-匿名内部类、反射的基本用法、动态代理、动态代理封装RPC框架

匿名内部类

Person类

package day14.AnnonymouseClass;

public class Person {

	public String name;
	public int age;

	public Person() {

		// TODO Auto-generated constructor stub
	}

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

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

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

	public void say() {
		System.out.println(this.name);
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

}

chinese类基础于Person类

package day14.AnnonymouseClass;

public class Chinese extends Person{
	@Override
	public void say() {
		System.out.println("我是中国人"+this.name);
	}

}

匿名内部类demo

package day14.AnnonymouseClass;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

//普通类的匿名内部类,不用建一个类文件,可以直接在类体内部写

public class AnnonymouseClass {
	public static void main(String[] args) {
		Person person = new Person();
		person.name = "人";
		Chinese chinese = new Chinese();
		chinese.name = "铁蛋";
		Person p = new Person() {
		}; // Person的子类,匿名。。//多态:父类的变量来引用子类的对象

		Person p2 = new Person() {

			public void say() {
				System.out.println("我是美国人:" + this.name);
			}

		};
		p2.name = "Tom";

		person.say();
		chinese.say();
		p2.say();

		/**
		 * 对接口使用匿名内部类
		 */

		Person person2 = new Person("zhang", 18);
		Person person3 = new Person("li", 20);

		// 对list中的对象按照某个属性进行排序
		ArrayList<Person> list = new ArrayList<>();
		list.add(person2);
		list.add(person3);
		Collections.sort(list, new Comparator<Person>() {

			@Override
			public int compare(Person p1, Person p2) {
				if (p1.getAge() < p2.getAge()) {
					return 1;
				}
				return -1;
			}

		});

		for (Person pp : list) {
			System.out.println(pp);
		}

	}
}

反射的基本用法以及配置文件的应用

接口类:

package day14.reflectAndProxy;

public interface LoginService {

	public void say();

	public void say(String name);

	public void eat();

	public String speak(String name);
}

实现类:

package day14.reflectAndProxy;

public class LoginServiceImpl implements LoginService {
	public void say() {
		System.out.println("你好:");
	}

	public void say(String name) {
		System.out.println("你好:" + name);
	}

	public void eat() {
		System.out.println("吃饭了");
	}

	public String speak(String name) {
		return "hello" + name;
	}
}

配置文件内容:
文件名:xx.properties
内容:
type=day14.reflectAndProxy.LoginServiceImpl
func=say
paramType=java.lang.String

反射的用法:

package day14.reflectAndProxy;

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

public class ReflectDemo {
	public static void main(String[] args) throws Exception {

		
//普通的调用		
//		LoginServiceImpl impl = new LoginServiceImpl();
//		 
//		impl.say();
//		impl.say("zhang");
//		impl.eat();
//		
//		String speak = impl.speak("lisi");
//		System.out.println(speak.toUpperCase());//变为大写

		/*
		 * 反射的方式构造对象,调用方法
		 * 
		 */

//		 String type = "day14.reflect.LoginServiceImpl";
//		 String func = "say";
//		 String paramType = "java.lang.String";
		
		//通过加载配制文件来获取要调用的类名、方法以及参数
		Properties props = new Properties();
		// props.load(new FileInputStream("D:/"))从绝对路径加载
		// 从工程的类的相对路径中加载
		props.load(ReflectDemo.class.getClassLoader().getResourceAsStream("xx.properties"));
		String type = props.getProperty("type");
		String func = props.getProperty("func");
		String paramType = props.getProperty("paramType");

		
		//通过类名和方法、方法参数类型,来反射的构造的方法构造对象,并调用方法
		// 类本身是一个java文件,在运行的时候会变成一个Class文件
		// 所以我们可以根据类名拿到一个类的Class
		Class<?> forName = Class.forName(type);// class
		Object instance = forName.newInstance();// 用class调用它的构造方法,产生一个LoginServiceImpl的对象----------class.newInstance()得到一个类的对象
		Method method = forName.getMethod(func, Class.forName(paramType));// 类名,,,参数类类名的Class----class.getMethod()得到一个类的方法(类名,参数类的class)

		method.invoke(instance, "哈哈哈");// 调用方法是在对象上调用,参数-------------方法调用--对象---参数

	}
}

动态代理

根据一个或者多个接口,用jdk的Proxy框架构造出一个“动态代理类”的对象(动态代理对象)
那么,这个动态代理对象上就具备那些接口上的方法
只不过,这些方法的具体逻辑,是定义在InvocationHandler实现类的invoke()方法中;

接口类

package day14.reflectAndProxy;

public interface LoginService {

	public void say();

	public void say(String name);

	public void eat();

	public String speak(String name);
}

接口实现类

package day14.reflectAndProxy;

public class LoginServiceImpl implements LoginService {
	public void say() {
		System.out.println("你好:");
	}

	public void say(String name) {
		System.out.println("你好:" + name);
	}

	public void eat() {
		System.out.println("吃饭了");
	}

	public String speak(String name) {
		return "hello" + name;
	}
}

动态代理类

package day14.reflectAndProxy;
/*
 * 动态代理就是在已知接口上 可以自己让接口中的方法做什么,类似于实现接口,方法都封装在了InvocationHandler()接口的实现类中
 * 
 */

import java.lang.reflect.Proxy;

public class ProxyDemo {
	public static void main(String[] args) {
		//构造一个LoginService接口的动态代理对象,,该方法是在jdk中定义的。注意参数前两个都和代理的接口有关,第三个参数是处理逻辑的类的对象,该类需要实现InvocationHandler接口
		LoginService o = (LoginService) Proxy.newProxyInstance(LoginService.class.getClassLoader(), new Class<?>[] {LoginService.class},new MyInvocationHandler());
		o.eat();
		String speak = o.speak("haha");//传参到动态代理的实现类中然后在方法中调用接口的实现类的方法
		System.out.println(speak);
		o.say();
		o.say("我是参数");
	}
}

动态代理逻辑封装类–接口InvocationHandler的实现类MyInvocationHandler

package day14.reflectAndProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler{

	
		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			//判断调用的是哪个方法
			if(method.getName().equals("eat")) {
				System.out.println("我一点也不喜欢吃");//调用该方法所做的事,可以自己定义
			}
			if(method.getName().equals("speak")) {
				String speak = new LoginServiceImpl().speak((String)args[0]); //在此也可调用接口实现类的方法
				
				return speak;
			}
			if(method.getName().equals("say")) {//判断方法名
				if(method.getParameters().length>0) {//判断是否有参数
					System.out.println("你调用的是say():"+args[0]);
				}else {
					System.out.println("你调用的是say(),没有参数");
				}
			}
			return null;
		}
	
	}

动态代理封装RPC框架

核心思想:给客户端一个动态代理对象,客户就以为拿到了服务端的一个实现类的对象,就愉快地凋起了方法,他还以为真的在他的机器上调到了这个方法
而本质上,他的调用行为被我们提供的动态代理对象上的invoke所拦截,在invoke中向远程服务器进行了通信交互,拿到结果,再返回给用户

客户端用的是day13.fin中的客户端
先是保存数据:

package day13.find;

import java.io.DataOutputStream;
import java.io.FileOutputStream;

public class SaveData {
	
	public static void main(String[] args) throws Exception {
		
		Product p0 = new Product(0, "苹果", 10.5f);
		Product p1 = new Product(1, "泰国榴莲", 16.5f);
		Product p2 = new Product(2, "菠萝", 20.5f);
		Product p3 = new Product(3, "菠萝蜜", 30.5f);
		Product p4 = new Product(4, "香蕉", 19.5f);
		
		save(p0);
		save(p1);
		save(p2);
		save(p3);
		save(p4);
		
	}
	
	public static void save(Product p) throws Exception {
		
		// 将数据按照既定的规则存入文件中
		// id占4个字节,name占20字节,price占4个字节
		DataOutputStream dout = new DataOutputStream(new FileOutputStream("d:/p.dat",true));
		
		dout.writeInt(p.getId()); //写入id
		
		byte[] bytes = p.getName().getBytes("GBK");
		byte[] b = new byte[20];
		// jdk提供的数组拷贝工具方法: 参数1:源数据数组  参数2:从源数组的第几个位置开始拷贝
		// 参数3 :目标数组   参数4:目标数组中放数据的起始位置  参数5:拷贝的长度
		System.arraycopy(bytes, 0, b, 0, bytes.length);
		dout.write(b);  // 将商品名写入文件,占20个字节
		
		dout.writeFloat(p.getPrice());  //将价格按照float数写入文件,占4个字节
		
		dout.close();
		
	}
}

读取数据类:

package day13.find;

import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

public class ReadData {

	/**
	 * 根据id查找商品
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	public Product findProductById(int id) throws Exception {

		// 可以从文件中任何位置开始读数据的工具:RandomAccessFile
		RandomAccessFile raf = new RandomAccessFile("d:/p.dat", "r");

		// 读id为2的那个商品的数据
		long pos = id * 28;

		// 让raf的读取位置跳到指定的pos位置
		raf.seek(pos);

		// 然后开始读数据即可
		// 先读4个字节返回一个整数
		int pId = raf.readInt();

		// 再读20个字节
		byte[] b = new byte[20];
		int read = raf.read(b);
		// 然后将这20个字节转成字符串,但是尾部有大量空格
		String string = new String(b);
		// 去掉首尾的空格
		String name = string.trim();

		// 再读价格
		float price = raf.readFloat();

		raf.close();

		Product prodcut = new Product(pId, name, price);
		return prodcut;
	}

	/**
	 * 根据名称查找商品
	 * 
	 * @throws Exception
	 **/

	public List<Product> findProductByName(String keyword) throws Exception {

		ArrayList<Product> pList = new ArrayList<>();

		// 可以从文件中任何位置开始读数据的工具:RandomAccessFile
		RandomAccessFile raf = new RandomAccessFile("d:/p.dat", "r");
		int i = 0;
		while ((i + 1) * 28 <= raf.length()) {
			raf.seek(4 + 28 * i); // 将读取位置定位到名称字段的起始位置
			byte[] b = new byte[20];
			raf.read(b);
			String name = new String(b).trim();
			if (name.contains(keyword)) {
				raf.seek(i * 28); // 回到这条数据的起始位置
				int id = raf.readInt(); // 读id数据
				raf.read(b); // 读名称字段
				float price = raf.readFloat(); // 读价格字段
				pList.add(new Product(id, name, price)); // 将符合条件的这条数据加入list中
			}

			i++;
		}

		return pList;
	}

	/**
	 * 根据价格查找商品
	 **/

}

Produnct类

package day13.find;

import java.io.Serializable;

public class Product implements Serializable {

	private int id;
	private String name;
	private float price;

	public Product(int id, String name, float price) {
		this.id = id;
		this.name = name;
		this.price = price;
	}

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Product [id=" + id + ", name=" + name + ", price=" + price + "]";
	}

}

服务器一方:

package day13.find;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 数据库服务器
 * 
 * @author ThinkPad
 *
 */
public class NewBiDbServer {

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

		ServerSocket ss = new ServerSocket(3305);
		ReadData readData = new ReadData();

		while (true) {
			Socket sc = ss.accept();
			new Thread(new FindDataRunnable(sc,readData)).start();

		}

	}

}

服务器功能的封装类:

package day13.find;

import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.List;

public class FindDataRunnable implements Runnable {

	Socket sc;
	ReadData readData;

	public FindDataRunnable(Socket sc, ReadData readData) {
		this.sc = sc;
		this.readData = readData;
	}

	@Override
	public void run() {
		try {
			InputStream in = sc.getInputStream();
			OutputStream out = sc.getOutputStream();

			ObjectOutputStream oos = new ObjectOutputStream(out);

			/**
			 * 客户端发过来的请求有两种情况: 1、SELECT * FROM p.dat WHERE id=3 // 想根据id查询商品数据 2、SELECT *
			 * FROM p.dat WHERE name like 菠萝 // 根据名称关键字查询商品数据
			 */
			byte[] b = new byte[1024];
			int num = in.read(b);

			String command = new String(b, 0, num);
			if (command.contains("id")) {
				// 根据id去帮用户查找商品
				String idStr = command.substring(command.indexOf("=") + 1);
				int id = Integer.parseInt(idStr);
				Product p = readData.findProductById(id);
				//发送一个对象
				oos.writeObject(p);

				out.close();
				sc.close();
				oos.close();
				in.close();
			} else {
				// 根据名称关键字去查找商品
				String[] split = command.split(" ");
				String keyWord = split[split.length - 1];

				List<Product> pList = readData.findProductByName(keyWord);

				// 返回数据给客户端
				oos.writeObject(pList);
				// TODO
				out.close();
				oos.close();
				in.close();
				sc.close();
			}

		} catch (Exception e) {

		}

	}

}

加客户端一方:
封装ReadData功能的接口

package day14.rpc.clientServiceinday13;

import java.util.List;

import day13.find.Product;

public interface ReadData {
	Product findProductById(int id) throws Exception;

	List<Product> findProductByName(String keyword) throws Exception;
}

读取服务端数据的工具类ReadDataUtil--------在动态代理中实现网络的连接

package day14.rpc.clientServiceinday13;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.util.List;

import day13.find.Product;

public class ReadDataUtil {
	public ReadData getInstance() {
		ReadData d = (ReadData) Proxy.newProxyInstance(ReadData.class.getClassLoader(),
				new Class<?>[] { ReadData.class }, new InvocationHandler() {

					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						String name = method.getName();
						if (name.equals("findProductById")) {
							Socket sc = new Socket("127.0.0.1", 3305);
							//发送请求
							OutputStream out = sc.getOutputStream();
							out.write(("id="+args[0]).getBytes());
							//接受结果
							InputStream in = sc.getInputStream();
							ObjectInputStream ois = new ObjectInputStream(in);
							
							Product p = (Product) ois.readObject();
							
							in.close();
							out.close();
							sc.close();
							ois.close();
							return p;
						
						} else {
							Socket sc = new Socket("192.0.0.1", 10000);
							//发送请求
							OutputStream out = sc.getOutputStream();
							out.write(("name= "+args[0]).getBytes());
							//接受结果
							InputStream in = sc.getInputStream();
							ObjectInputStream ois = new ObjectInputStream(in);
							List<Product> plist = (List<Product>)ois.readObject();
							in.close();
							out.close();
							ois.close();
							sc.close();
							return plist;
						}

						
					}

				});
		return d;
	}
}

测试类—在客服端调用服务端的方法来查询服务端的数据

package day14.rpc.clientServiceinday13;

import day13.find.Product;

public class Test {
	public static void main(String[] args) throws Exception {
		ReadDataUtil util = new ReadDataUtil();
		ReadData readData = util.getInstance();
		Product p = readData.findProductById(4);
		System.out.println(p);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值