method.invoke()和invoke()简单理解

本文深入探讨Java反射机制中的method.invoke方法,解释其在调用实现类方法时的应用,并详细解析通过Proxy.newProxyInstance创建动态代理类的过程,包括参数说明及内部invoke方法的执行流程。
该文章已生成可运行项目,

首先说下作用,method.invoke(Object obj,Object args[])的作用就是调用method类代表的方法,其中obj是对象名,args是传入method方法的参数

举个例子:如果接口中没有close方法,但是实现类中提供了close,那么就可以用反射来处理,调用实现类的close方法

invoke()方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。

invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回.

有四种获得method对象的方法,返回结果是method对象,或者说是 方法的全限定名
  一共有4种方法,全部都在Class类中:
    - getMethods(): 获得类的public类型的方法
    - getMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型
    - getDeclaredMethods(): 获取类中所有的方法(public、protected、default、private)
    - getDeclaredMethod(String name, Class[] params): 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型

另外关于代理类,以下Proxy.newProxyInstance的相关内容 是整理自B站的一个视频,

链接如下:https://www.bilibili.com/video/av15369076?p=19

Proxy.newProxyInstance

 *         参数1:loader ,类加载器,动态代理类 运行时创建,任何类都需要类加载器将其加载到内存。

 *                一般情况:方式1:当前类.class.getClassLoader();

 *                                方式2:目标类实例.getClass().get...

 *         参数2:Class[] interfaces 代理类需要实现的所有接口

 *                方式1:目标类实例.getClass().getInterfaces()  ;但是需要注意:这种方法只能获得自己接口,不能获得父元素接口

 *                方式2:new Class[]{UserService.class}  

 *                例如:jdbc 驱动  --> DriverManager  不能获得接口 Connection

 *         参数3:InvocationHandler  处理类,接口,必须进行实现类,一般采用匿名内部

 *         提供invoke 方法,代理类的每一个方法执行时,都将调用一次invoke

 *         参数31:Object proxy :代理对象

 *         参数32:Method method : 代理对象当前执行的方法的描述对象(反射)

*                  执行方法名:method.getName()

*           参数33:Object[] args :方法实际参数

Invoke方法内部:

*                  执行方法:method.invoke(对象,实际参数)

 

public class MyBeanFactory {
	
	public static UserService createService(){
		//1 目标类
		final UserService userService = new UserServiceImpl();
		//2切面类
		final MyAspect myAspect = new MyAspect();
		/* 3 代理类:将目标类(切入点)和 切面类(通知) 结合 --> 切面
		 * 	Proxy.newProxyInstance
		 * 		参数1:loader ,类加载器,动态代理类 运行时创建,任何类都需要类加载器将其加载到内存。
		 * 			一般情况:当前类.class.getClassLoader();
		 * 					目标类实例.getClass().get...
		 * 		参数2:Class[] interfaces 代理类需要实现的所有接口
		 * 			方式1:目标类实例.getClass().getInterfaces()  ;注意:只能获得自己接口,不能获得父元素接口
		 * 			方式2:new Class[]{UserService.class}   
		 * 			例如:jdbc 驱动  --> DriverManager  获得接口 Connection
		 * 		参数3:InvocationHandler  处理类,接口,必须进行实现类,一般采用匿名内部
		 * 			提供 invoke 方法,代理类的每一个方法执行时,都将调用一次invoke
		 * 				参数31:Object proxy :代理对象
		 * 				参数32:Method method : 代理对象当前执行的方法的描述对象(反射)
		 * 					执行方法名:method.getName()
		 * 					执行方法:method.invoke(对象,实际参数)
		 * 				参数33:Object[] args :方法实际参数
		 * 
		 */
		UserService proxService = (UserService)Proxy.newProxyInstance(
								MyBeanFactory.class.getClassLoader(), 
								userService.getClass().getInterfaces(), 
								new InvocationHandler() {	
									@Override
									public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
										//前执行
										myAspect.before();	
										//执行目标类的方法
										Object obj = method.invoke(userService, args);				
										//后执行
										myAspect.after();
										
										return obj;
									}
								});
		return proxService;
	}

}

 

本文章已经生成可运行项目
在 Java 中,`method.invoke()` `MethodHandle` 都是用来实现反射调用的方法,但它们的使用方式、性能灵活性有所不同。下面分别介绍它们并进行对比。 ### 1. `method.invoke()` `method.invoke()` 是 `java.lang.reflect.Method` 类的方法,用于通过反射调用类的方法。 #### 示例代码: ```java import java.lang.reflect.Method; public class ReflectExample { public void sayHello(String name) { System.out.println("Hello, " + name); } public static void main(String[] args) throws Exception { ReflectExample example = new ReflectExample(); Method method = ReflectExample.class.getMethod("sayHello", String.class); method.invoke(example, "World"); // 输出: Hello, World } } ``` #### 特点: - 简单易用,适合一次性调用。 - 每次调用都会进行参数类型检查自动装箱拆箱。 - 性能较低,因为每次调用都要进行方法查找参数检查。 --- ### 2. `MethodHandle` `MethodHandle` 是 Java 7 引入的一个新特性(位于 `java.lang.invoke` 包中),用于更高效地执行方法调用,尤其是在需要多次调用的情况下。 #### 示例代码: ```java import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; public class MethodHandleExample { public void sayHello(String name) { System.out.println("Hello, " + name); } public static void main(String[] args) throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh = lookup.findVirtual(MethodHandleExample.class, "sayHello", MethodType.methodType(void.class, String.class)); mh.invoke(new MethodHandleExample(), "World"); // 输出: Hello, World } } ``` #### 特点: - 性能更高,适合高频调用。 - 支持更灵活的调用方式(如绑定参数、组合调用等)。 - 更接近 JVM 底层机制,适合框架开发性能敏感场景。 --- ### 对比总结: | 特性 | `method.invoke()` | `MethodHandle` | |--------------------|--------------------------------------------|----------------------------------------| | 性能 | 较低,适合少量调用 | 更高,适合高频调用 | | 使用难度 | 简单易用 | 稍复杂,需要理解 `MethodType` 等概念 | | 参数处理 | 自动装箱拆箱类型检查 | 需要严格匹配类型 | | 调用灵活性 | 固定调用方式 | 支持绑定、组合等高级操作 | | 适用场景 | 快速原型、简单反射调用 | 高性能框架、动态语言实现、JVM 优化 | --- ###
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值