Spring BeanWrapper分析

来源:互联网 发布:注册域名哪个网站好 编辑:程序博客网 时间:2024/06/05 13:06

最近在读DispatcherServlet 源代码,看到父级类org.springframework.web.servlet.HttpServletBean中关于BeanWrapper的一段代码, 继续追看下去,发现

BeanWrapper 是spring 底层核心的JavaBean包装接口, 默认实现类BeanWrapperImpl.所有bean的属性设置都是通过它来实现。

@Overridepublic 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")); }




0 0