Java反射的应用

补充

针对上篇文章《JAVA反射原理》的图,再稍作补充:

这个图是上篇博客中图的一部分,实际上,这部分才是反射的核心,即:对象、class的相互关系:

  • 对象实例化后,在头部保留其class引用,即对象→class
  • 根据加载的class,实例化对象,即class→对象

如上篇文章所说,我们关注反射,是因为反射可以达到以下作用:

  • 根据一个字符串形式的类名加载类
  • 由加载的类直接实例化对象
  • 已知一个对象,获取其类信息(接口、函数……)

这些作用听起来没什么大不了,但是合理使用,威力很大:Struts、Hibernate、Spring、动态代理……没有反射,这些都白搭。

Struts

此处以Struts1为例,来看一下struts-config.xml:

<struts-config>
	<form-beans>
		<form-bean name="loginForm" type="com.tgb.struts.LoginActionForm"/>
	</form-beans>

	<action-mappings>
		<action path="/login"
				type="com.tgb.struts.LoginAction"
				name="loginForm"
				scope="request"
				>
			<forward name="success" path="/login_success.jsp" />
			<forward name="error" path="/login_error.jsp"/>
		</action>
	</action-mappings>
</struts-config>

根据Struts1的运行机制,我们知道在ActionServlet截获请求后,会将页面数据存放到一个ActionForm中,然后把此ActionForm交由Action处理,使用如下:

LoginActionForm laf = (LoginActionForm)form;

你可以发现ActionForm传给Action时,已经是一个对象了,这个对象从哪里来的?我们知道对象来源有两种:

  • new(工厂、clone)
  • Class.newInstance()

很明显我们使用Struts并没有手动new过任何一个ActionForm或者Action;Struts倒是想替你new,但是我们知道Class1 obj=new Class1()需要手动编程(工厂、clone和这属于一类),所以new这条路就被封死了。

Struts也仅仅知道你配置了一个loginForm,类是com.tgb.struts.LoginActionForm……,没错,Struts就是使用反射加载这些类,从而实例化ActionForm和Action的,大致过程如下:

  • ActionServlet截取请求
  • 根据请求对应的Struts配置,使用Class.forName("com.tgb.struts.LoginActionForm")获取loginForm对象;
  • 调用ActionForm的各种setter赋值表单值
  • 根据Struts配置,使用Class.forName("com.tgb.struts.LoginAction")获取loginAction对象
  • 将loginForm传给loginAction
  • 强制转化后,在loginAction中使用loginForm

Hibernate

Hibernate使用了ORM(Object/Relation Mapping)机制,R(Relation)来自数据库,O(Object)呢?来看一下hibernate映射文件:

<hibernate-mapping >
	<class name="com.tgb.hibernate.Person"  table="t_person">
		<id name="id">
			<generator class="foreign" >
				<param name="property">idCard</param>
			</generator>
		</id>
		<property name="name" />
		<one-to-one name="idCard"  constrained="true" />
	</class>
</hibernate-mapping>

看到<class name="com.tgb.hibernate.Person" table="t_person">,和上面说的Struts一样,也是使用到反射,以Hibernate的根据主键获取对象为例:session.get(Person.class, "0001"):

  • 生成sql语句,操作数据库获得数据
  • Class.forName("com.tgb.hibernate.Person")获取Person实例
  • 调用Person的setter对属性赋值
  • 返回此Person对象

Spring

Spring是一个大工厂,用于组织对象之间的关系,配置如下:

<bean id="userManager" class="com.tgb.usermgr.manager.UserManagerImpl">
	<property name="logManager" ref="logManager"/>
</bean>
<bean id="logManager" class="com.tgb.usermgr.manager.LogManager" />

简单说IoC的过程如下:

  • Class.forName("com.tgb.usermgr.manager.UserManagerImpl")实例化userManagerImpl
  • Class.forName("com.tgb.usermgr.manager.LogManager")实例化logManager
  • 调用userManagerImpl的setLogManager,注入logManager
  • 当使用userManagerImpl,已经是处理完依赖关系的userManagerImpl

可以说,只要在配置文件有对类名的标记,基本上就是为了利用到反射的特性。

动态代理

上面说的都是关于class→对象的demo,而反射的作用不止这个,再来看看动态代理中的反射。由于动态反射中的内容较多,会单独再说,我们只看其中一部分,与invoke相关的内容。

Person

package reflection;

public class Person {

	public void eat()
	{
		System.out.println("im eating");
	}
}

TestMethod

package reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestMethod {

	public static void main(String [] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException
	{
		//获取Person类
		Class clazz=Class.forName("reflection.Person");
		//实例化对象
		Person p=(Person)clazz.newInstance();
		//得到person的eat方法
		Method m=clazz.getDeclaredMethod("eat",new Class[]{});
		//执行person的eat方法
		m.invoke(p, new Object[]{});
	}
}

如上,知道一个类的某个方法名,再有这个类的实例,我们就可以执行这个函数。有对象,有函数名,我直接obj.method()不就行了?这就跟用不用MVC道理一样,不用照样可以完成功能,但是却少了灵活性。

基于这种方法名的调用,我们可以延迟调用方法,这也给了我们很多的操作空间,比如我先执行一段代码,再根据函数名调用函数,再执行后续的代码……这不就是动态代理的应用么。

总结

关于反射细节,如在JVM中的执行流程,较为复杂,待以后整理清楚再说。

Java反射的应用

时间: 2024-10-04 13:53:19

Java反射的应用的相关文章

Java反射

1. 介绍 反射是一种能够在程序运行时动态访问.修改某个类中任意属性和方法的机制. 具体:对于任意一个类,都能够知道这个类的所有属性和方法对于任意一个对象,都能够调用它的任意一个方法和属性 在运行时,当加载完类之后,JVM在堆内存中会自动产生一个Class类型的对象,这个对象包含了完整的类的结构信息 这个Class对象就像一面镜子,透过这个镜子看到类的结构 那么,如何得到这个Class对象呢?以下可否 Class c = new Class(); 答案是不行的,因为Class的构造函数定义为私有

Java 反射详解

反射反射,程序员的快乐,今天你快乐了吗?如果你不快乐,没关系,接下来让你快乐起来! 一.什么是反射? 通过百度百科我们可以知道,Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性.而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C

java反射机制(一)—— 利用反射机制实例化对象

一.Java有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载.探知.使用编译期间完全未知的classes.换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体.或对其fields设值.或唤起其methods.(度娘文库是这么说的) 二.这篇文章主要介绍一下通过反射机制去实例化一个类的对象,然后调用其方法.本文主要介绍两种方式,第一种就是通过构造函数来实例化,第二种就是通过Cl

java 反射 详解

本文来自:blog.csdn.net/ljphhj JAVA反射机制:   通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没用,下面我们看看实践 Demo - Demo: package cn.lee.demo; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import

【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】

方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; private String name; private Boolean flag; public Integer getNum() { return num; } public void setNum(Integer num) { this.num = num; } public String getNam

java 反射类的理解与应用

本文主要解析的类是: ClassLodaer,Class,Field,Method,Constructor. 本文的目标很简单,只是对这些常用的反射类进行简单解释.对这些类中常用方法进行介绍. JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对象:在

Java 反射机制

使用 Java 反射机制可以在运行时期检查 Java 类的信息,检查 Java 类的信息往往是你在使用 Java 反射机制的时候所做的第一件事情,通过获取类的信息你可以获取以下相关的内容: Class 对象 类名 修饰符 包信息 父类 实现的接口 构造器 方法 变量 注解 除了上述这些内容,还有很多的信息你可以通过反射机制获得,如果你想要知道全部的信息你可以查看相应的文档 JavaDoc for java.lang.Class 里面有详尽的描述. 在本节中我们会简短的涉及上述所提及的信息,上述的

Java 反射,开发框架必备技能

通过反射技术我们将上面的统一资源定位付(URL) 映射到Class 相当于 class: news method: list parameter: 2 差不多就是下面样子 class News{ public String list(String catagory_id){ ... ... } } 我们只需要在框架核心中分析 url 然后调用对应的方法下载,于此同时将参数传递过去. Class<?> cls = Class.forName("cn.netkiller.reflect.

Java反射与代理

Java反射机制与动态代理,使得Java更加强大,Spring核心概念IoC.AOP就是通过反射机制与动态代理实现的. 1       Java反射 示例: User user = new User(); user.setTime5Flag("test"); Class<?> cls = Class.forName("com.test.User"); //接口必须public,无论是否在本类内部使用!或者使用cls.getDeclaredMethod()

Java反射机制浅析

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. "程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言".从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言.但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载.探知.使用