最近在读DispatcherServlet 源代码,看到父级类org.springframework.web.servlet.HttpServletBean中关于BeanWrapper的一段代码, 继续追看下去,发现
BeanWrapper 是spring 底层核心的JavaBean包装接口, 默认实现类BeanWrapperImpl.所有bean的属性设置都是通过它来实现。
@Override
public final void init() throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
}
// Set bean properties from init parameters.
try {
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
throw ex;
}
// Let subclasses do whatever initialization they like.
initServletBean();
if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类 自动注入工厂抽象类
@Override
public Object configureBean(Object existingBean, String beanName) throws BeansException {
markBeanAsCreated(beanName);
BeanDefinition mbd = getMergedBeanDefinition(beanName);
RootBeanDefinition bd = null;
if (mbd instanceof RootBeanDefinition) {
RootBeanDefinition rbd = (RootBeanDefinition) mbd;
bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition());
}
if (!mbd.isPrototype()) {
if (bd == null) {
bd = new RootBeanDefinition(mbd);
}
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.allowCaching = false;
}
<span style="color:#FF0000;"> BeanWrapper bw = new BeanWrapperImpl(existingBean);</span>
initBeanWrapper(bw);
populateBean(beanName, bd, bw);
return initializeBean(beanName, existingBean, bd);
}
BeanWrapperImpl 继承了属性编辑注册功能
如何设置值 :
@Override
public void setPropertyValue(String propertyName, Object value) throws BeansException {
BeanWrapperImpl nestedBw;
try {
//获取嵌套的属性, like map[my.key], 没有嵌套属性就返回自己
nestedBw = getBeanWrapperForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}
看下面具体方法的实现
/**
* Recursively navigate to return a BeanWrapper for the nested property path.
* @param propertyPath property property path, which may be nested
* @return a BeanWrapper for the target bean
*/
protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) {
int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
// Handle nested properties recursively.
if (pos > -1) {
String nestedProperty = propertyPath.substring(0, pos);
String nestedPath = propertyPath.substring(pos + 1);
//递归获取最后一个属性
BeanWrapperImpl nestedBw = getNestedBeanWrapper(nestedProperty);
return nestedBw.getBeanWrapperForPropertyPath(nestedPath);
}
else {
return this;
}
}
自己实现了个小例子:
public class HelloWorld {
private String msg = null;
private Date date = null;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
package com.sunkey.test;
public class Pepole {
private String name;
private int sex;
private HelloWorld helloWorld;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public HelloWorld getHelloWorld() {
return helloWorld;
}
public void setHelloWorld(HelloWorld helloWorld) {
this.helloWorld = helloWorld;
}
}
测试代码:
@Test
public void testBeanWapper() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Object obj = Class.forName("com.sunkey.test.HelloWorld").newInstance();
BeanWrapper bw = new BeanWrapperImpl(obj);
bw.setPropertyValue("msg", "HellowWorld");
bw.setPropertyValue("date", new Date());
System.out.println(bw.getPropertyValue("date") + "\n" + bw.getPropertyValue("msg"));
}
@Test
public void testNestedBeanWapper() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Object obj = Class.forName("com.sunkey.test.HelloWorld").newInstance();
BeanWrapper bw = new BeanWrapperImpl(obj);
bw.setPropertyValue("msg", "HellowWorld");
bw.setPropertyValue("date", new Date());
Object objP = Class.forName("com.sunkey.test.Pepole").newInstance();
BeanWrapper pbw = new BeanWrapperImpl(objP);
pbw.setPropertyValue("name", "jack");
pbw.setPropertyValue("helloWorld", obj);
System.out.println(pbw.getPropertyValue("name") + "\n" + pbw.getPropertyValue("helloWorld.msg"));
pbw.setPropertyValue("helloWorld.msg", "HellowWorld修改过");
System.out.println(pbw.getPropertyValue("name") + "\n" + pbw.getPropertyValue("helloWorld.msg")); }