Java 反射机制(三) Spring中Bean注入分析

在使用XML文件配置Spring Bean的时候,底层实现就是使用反射机制实现的。工作之余跟了Spring的源码,但是至今还毫无头绪,以后得空再认真阅读。本文时根据自己的分析和对反射的实践,得出的结论。

在ApplicationContext.xml 中配置Bean

	<bean id="myCar" class="com.jnk.spring.beans.Car">
		<property name="carName" value="bmw"></property>
		<property name="driver" value="Jack"></property>
	</bean>

然后使用ApplicationContext.getBean获取这个Bean

public class MyContext
{
	static ApplicationContext acp = new FileSystemXmlApplicationContext(
			"D:/MySoftware/eclipse/workspace/Spring-404/src/com/jnk/spring/beans.xml");

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		Car myCar = acp.getBean("myCar", Car.class);
		System.out.println(myCar);

		StudentService stuServ = acp.getBean("studentService", StudentService.class);
		stuServ.addStudent("Nonkey");
	}

}

在xml配置属性的时候并没有指定参数的类型,因此无法单独获取这个方法,因为Class.getMethod 方法的时候,如果这个方法有参数,就必须指定参数类型,所以,Spring应该时直接使用 getMethods方法,得到所有的方法,然后再遍历得到的方法数组,匹配根据property 节点中的name属性拼装得到的setter方法名称,进行属性注入。

private static void springTest()
	{
		try
		{
			HashMap<String, Object> objContainer = new HashMap<String, Object>();// 对象容器,存放所有bean对象
			Class<?> obj = Class.forName("com.jnk.think.java.chapter.reflect.SingleTonUtils");// 获取Class对象
			/*
			 * 获取无参构造器,带 Declared 的方法可以获取私有方法和属性,不带 Declared 的方法只能获取私有方法和属性
			 */
			Constructor<?> constructor = obj.getDeclaredConstructor();
			Object newInstance = constructor.newInstance();// 使用构造器创建一个新对象,如果没有无参构造方法,则报错

			HashMap<String, Object> propertyNameValueMap = new HashMap<String, Object>();// 读取配置文件获取属性名称和取值的映射
			Method[] methods = obj.getMethods(); // 获取当前Bean的所有方法
			// 遍历属性名称和取值的映射,查询对象方法,执行映射
			for (Entry<String, Object> iterable : propertyNameValueMap.entrySet())
			{
				String methodName = "set" + iterable.getKey().toUpperCase().charAt(0) + iterable.getKey().substring(1);
				Method eMethod = getMethodByName(methods, methodName); // 根据这个方法名获取方法对象
				if (null == eMethod)
				{
					// 如果没找到直接报异常
				}
				eMethod.invoke(newInstance, iterable.getValue());// 将属性注入到对象当中
			}
			objContainer.put("对象ID", newInstance); // 将此对象添加到Spring容器

		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}
还有中猜想,直接设置属相值而不通过setter方法,但是当bean没有给定public的setter的时候,会报异常:
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'carName' of bean class [com.jnk.spring.beans.Car]: Bean property 'carName' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
而Feild.set()方法时不调用setter方法的,所以这种猜想并不成立。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值