20140314 一起学Spring Framework 002 Bean属性设值的自动类型转换 和 scope概念

上一篇提到通过反射去找setter方法时代码有问题,所以加了这个测试以确保程序没问题

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
	<bean id="gordon" class="gordon.study.spring.sample.Employee">
		<property name="name" value="Gordon" />
		<property name="age" value="32" />
		<property name="male" value="true" />
		<property name="birthday" value="1982-07-05" />
		<property name="salary" value="817.52" />
	</bean>
</beans>

显然,测试目前无法通过,报  java.lang.NoSuchMethodException: gordon.study.spring.sample.Employee.setAge(java.lang.String)

(注意,birthday是java.util.Date类型。这样配置在spring中是会报错的)


既然我们不知道setter方法的参数是什么,那就只能获得当前class的所有方法,通过名字去找匹配的setter了。

一个潜在但不常见的问题是:如果存在同名的setter方法怎么办?比如 setMale(boolean isMale) 和 setMale(String s)(期待"Y“或”N“输入)同时存在。

由于Java在编译器这端不支持只有返回类型不相同的函数签名,所以get方法只能有一个。这就简化了问题,程序逻辑将设为:

1,如果有一个匹配的getter,那getter的返回类型决定了生效的setter方法;

2,如果没有getter,那参数为String的setter被选中;

3,随机选择一个。不做额外的智能匹配工作。


代码依然是体力活,唯一注意的是 Integer.class 与 int.class 不相同,即 Integer.class == int.class 为 false。所以写类型转换的代码的时候要注意

public class SimpleTypeConverter {

	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");

	public static Object convertTo(Class<?> type, String propertyValue) throws Exception {
		if (type == String.class) {
			return propertyValue;
		} else if (type == Integer.class || type == int.class) {
			return Integer.parseInt(propertyValue);


	// For multiple setter methods with same name:
	// 1. If there is a getter/is(only for boolean/Boolean) method. The setter
	// method which
	// needs the same type param as getter's return type should be used.
	// 2. Use the setter method which takes String type as param.
	// 3. Return a random setter method. Do not do any smart try for type
	// convert.
	private Method findSetterMethod(Method[] methods, Class<?> beanClass, String property) {
		Method getterMethod = getGetterMethodReturnType(methods, beanClass, property);
		Class<?> returnType = null;
		if (getterMethod != null) {
			returnType = getterMethod.getReturnType();
		}

		String setterStr = getSetterMethodString(property);

		Method setterMethodStringParam = null;
		Method someSetterMethod = null;
		for (Method method : methods) {
			if (method.getName().equals(setterStr) && method.getParameterTypes().length == 1) {
				if (returnType != null && method.getParameterTypes()[0].equals(returnType)) {
					return method;
				} else if (method.getParameterTypes()[0].equals(String.class)) {
					setterMethodStringParam = method;
				} else {
					someSetterMethod = method;
				}
			}
		}

		if (setterMethodStringParam != null) {
			return setterMethodStringParam;
		} else if (someSetterMethod != null) {
			return someSetterMethod;
		} else {
			throw new RuntimeException("Bean " + beanClass.getName() + " does not have the property " + property);
		}
	}

=====================================================================

至于scope,现在就两种:singleton和prototype

singleton是默认的,表示spring容器只会生成一个实例。而对于prototype类型,容器会在每次getBean的时候创建一个新的实例。

实现的话,只要在BeanDefinition中加上scope字段,其默认值是 singleton。对于propotype类型的bean,容器在创建完它们之后就不应该再继续持有这些对象的引用,以便垃圾收集。

public Object getBean(String beanName) throws Exception 
		if (beans.containsKey("beanName")) {
			return beans.get(beanName);
		}

		Object bean = createBean(beanName);

		if (beanDefinitions.get(beanName).getScope() == 0) {
			beans.put(beanName, bean);
		}

		return bean;
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值