java学习之路 之 反射机制综合练习题、动态代理实例

 在上一篇博文中我们已经进行了反射机制的习题练习,这里我们在做一个考察比较全面的练习,如下:

写一个类ReflectUtil类, 类中写一个静态方法Object methodInvoker(String classMethd) 此方法为无参方法如,

我们传入的实参字符串为:classMethod "java.lang.String.length()"就可以通过反射执行String类中的length方法、

 当传入的实参字符串为"com.atguigu.javase.reflect.Teacher.test()"就可以执行指定包下,指定类中的指定方法

具体实现如下:

package com.aguigu.javase.work;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
 写一个类ReflectUtil类, 类中写一个静态方法Object methodInvoker(String classMethd) 
此方法为无参方法如:
	classMethod "java.lang.String.length()"
 	com.atguigu.javase.reflect.Teacher.test()
*/
public class ReflectUtil {
	
	public static Object methodInvoker(String classMethd) throws ClassNotFoundException, 
																 NoSuchMethodException, 
																 SecurityException, 
																 InstantiationException, 
																 IllegalAccessException, 
																 IllegalArgumentException, 
																 InvocationTargetException {
		// 获取最后一个"."出现的下标
		int lastDot = classMethd.lastIndexOf(".");
		// 获取子字符串从第0下标到最后一个"."出现的下标,这个字符串即为类的全限定名称
		String className = classMethd.substring(0, lastDot);
		// 获取子字符串,为方法的名称
		String methodName = classMethd.substring(lastDot + 1, classMethd.length() - 2);
		 // 根据类名获取Class对象
		Class clazz = Class.forName(className);
		Method method = null;
		Class tmp = clazz;
		// 判断次方法是否存在
		while (tmp != null) {
			try {
				// 若存在,获取方法对象,以防是私有方法,使用getDeclaredMethod方法获取
				method = tmp.getDeclaredMethod(methodName);
				break;
			} catch (NoSuchMethodException e) {
				// 若不存在,在父类中获取此方法
				tmp = tmp.getSuperclass();
			}
		}
		Object object = clazz.newInstance();
		// 根据Class对象创建对象
		// 突破私有方法的禁锢性
		method.setAccessible(true);
		return method.invoke(object);
	}
	
	public static void main(String[] args) {
		try {
			Object object = methodInvoker("java.lang.String.length()");
			System.out.println(object);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
动态代理:客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。从而实现一个客户代理对象可以完成多个业务的代理。

动态的代理实例:一个代理可以完成房屋出租、售票等.....业务

// 动态的代理实例,一个代理可以完成房屋出租、售票等.....业务
package com.aguigu.javase.reflect;

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

// 创建一个HouseRent接口,其中有Rent方法(房屋出租)
interface HouseRent {
	public void rent();
}

// 创建一个FangDong类,实现HouseRent接口的Rent方法(房屋出租)
class FangDong implements HouseRent {
	@Override
	public void rent() {
		System.out.println("婚房, 请爱护");
	}
}

// 创建一个TrainTicket接口,其中有buy方法(售票)
interface TrainTicket {
	public void buy();
}

// 创建一个BeijingNan类,实现TrainTicket接口的buy方法(售票)
class BeiJingNan implements TrainTicket {
	@Override
	public void buy() {
		System.out.println("您请稍等, 正在出票...");
		for (int i = 0; i < 10000000; i++) {
			int j = i * i;
		}
	}
}

// 创建一个MyInvocationHandler类实现InvocationHandler接口,将被代理对象作为属性,实现对象的关联,并提供get,set方法
class MyInvocationHandler implements InvocationHandler {
	
	private Object target; // 被代理对象
	
	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

	// method方法调用必须需要一个真的被代理对象
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) // 第1个是代理对象, 第2个是代理方法, 第3个是方法需要实参
			throws Throwable {
		// 调用对象.getClass方法获取对的类模板,方法名的getName方法获取方法名
		System.out.println("动态代理代理对象[" + proxy.getClass() + "],方法[" + method.getName() + "]调用前");
		long time1 = System.currentTimeMillis();
		
		// 执行被代理对象的方法,并返回被代理对象类型的对象
		Object object = method.invoke(target, args);
		
		long time2 = System.currentTimeMillis();
		System.out.println("动态代理方法[" + method.getName() + "]执行完毕 , 共用了" + (time2 - time1) + "毫秒");
		
		return object;
	}
	
}

public class ProxyTest {
	
	public static void main(String[] args) {
		MyInvocationHandler h = new MyInvocationHandler();
		FangDong fd = new FangDong();
		h.setTarget(fd);//设置被代理对象
		HouseRent hRent = (HouseRent)Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), // 第一个参数是类加载器类加载器
															fd.getClass().getInterfaces(), // 代理类中的所有接口
															h); // 第三个参数是一个方法调用处理器(包含了对象原始对象的方法的进一步处理)
		hRent.rent();
		
		// 重复利用方法调用处理器
		h.setTarget(new BeiJingNan()); // 只需要改变被代理对象即可
		TrainTicket tt = (TrainTicket)Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), 
							   								 new Class[]{TrainTicket.class},
							   								 h);
		tt.buy();
	}
	
}


你可能感兴趣的:(【JavaEE】)