您现在的位置是:首页 > 正文

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

2024-02-01 01:10:42阅读 2

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

写一个类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();
	}
	
}


网站文章

  • 分布式发布订阅消息系统 Kafka 架构设计

    分布式发布订阅消息系统 Kafka 架构设计

    我们为什么要搭建该系统Kafka是一个消息系统,原本开发自LinkedIn,用作LinkedIn的活动流(activity stream)和运营数据处理管道(pipeline)的基础。现在它已为多家不...

    2024-02-01 01:10:35
  • 使用Axure+svn+httpd搭建自己的在线画图工具

    使用Axure+svn+httpd搭建自己的在线画图工具

    文章目录一、为什么要画图?二、Axure团队项目搭建三、Axure团队项目拉取四、​搭建Apache服务使用http协议访问svn安装httpd配置httpd添svn.conf配置配置http用户名密...

    2024-02-01 01:10:27
  • netty设计模式-责任链模式

    netty设计模式-责任链模式

    责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。 首先来看看责任链模式的四个要素: 1、责任处理器接口 2、创建链,添加删除责任处理器接口 3、上下文 4、责任链终止机制。 在netty里面,很明显channelHandler和Pipeline构成了责任链模式。让我们通过...

    2024-02-01 01:10:22
  • 根据二叉树的中序和后续遍历,求树的前序遍历(附Java代码实现)

    根据二叉树的中序和后续遍历,求树的前序遍历(附Java代码实现)

    根据树的中序遍历和后续遍历求前序遍历

    2024-02-01 01:09:52
  • 目标检测网络系列——YOLO V4

    YOLO4的设计目标也还是YOLO系列的主要关注点,就是要快。 The main goal of this work is designing a fast operating speed of an...

    2024-02-01 01:09:46
  • 如何不优雅的解决子组件丢失this.props的三个重要对象

    如何不优雅的解决子组件丢失this.props的三个重要对象

    把父组件的this.props暴力传给子组件在组件里就不能用this.props了 要用this.props.data 才相当于this.props然后就可以正常用这三个对象的属性和方法了 

    2024-02-01 01:09:39
  • SpringMVC(五):异常处理器

    作用:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行。工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)业务层抛出的异...

    2024-02-01 01:09:11
  • 力扣232 - 用栈实现队列【C语言实现】

    力扣232 - 用栈实现队列【C语言实现】

    力扣232 - 用栈实现队列,教你如何使用双栈实现队列操作

    2024-02-01 01:09:04
  • 友元函数练习

    #include &quot;stdafx.h&quot; #include&quot;iostream&quot; using namespace std; class Date; class Ti...

    2024-02-01 01:08:57
  • SIMD指令初学 热门推荐

    SIMD指令初学 热门推荐

    参考自:http://blog.csdn.net/gengshenghong/article/details/7008704(。。。。) SIMD 即 single instruction multiple data,单指令流多数据流,也就是说一次运算指令可以执行多个数据流,这样在很多时候可以提高程序的运算速度。 SIMD是CPU实现DLP(Data Level Para

    2024-02-01 01:08:28