Spring BeanWrapper分析

最近在读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")); }




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值