代码改变世界

Spring BeanWrapper分析

2017-06-26 11:35  dogdogwang  阅读(1911)  评论(0编辑  收藏  举报

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

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

 

[java] view plain copy
 
  1. @Override  
  2.     public final void init() throws ServletException {  
  3.         if (logger.isDebugEnabled()) {  
  4.             logger.debug("Initializing servlet '" + getServletName() + "'");  
  5.         }  
  6.   
  7.         // Set bean properties from init parameters.  
  8.         try {  
  9.             PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);  
  10.             BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);  
  11.             ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());  
  12.             bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));  
  13.             initBeanWrapper(bw);  
  14.             bw.setPropertyValues(pvs, true);  
  15.         }  
  16.         catch (BeansException ex) {  
  17.             logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);  
  18.             throw ex;  
  19.         }  
  20.   
  21.         // Let subclasses do whatever initialization they like.  
  22.         initServletBean();  
  23.   
  24.         if (logger.isDebugEnabled()) {  
  25.             logger.debug("Servlet '" + getServletName() + "' configured successfully");  
  26.         }  

 

 

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类 自动注入工厂抽象类

 

[java] view plain copy
 
  1. @Override  
  2.     public Object configureBean(Object existingBean, String beanName) throws BeansException {  
  3.         markBeanAsCreated(beanName);  
  4.         BeanDefinition mbd = getMergedBeanDefinition(beanName);  
  5.         RootBeanDefinition bd = null;  
  6.         if (mbd instanceof RootBeanDefinition) {  
  7.             RootBeanDefinition rbd = (RootBeanDefinition) mbd;  
  8.             bd = (rbd.isPrototype() ? rbd : rbd.cloneBeanDefinition());  
  9.         }  
  10.         if (!mbd.isPrototype()) {  
  11.             if (bd == null) {  
  12.                 bd = new RootBeanDefinition(mbd);  
  13.             }  
  14.             bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);  
  15.             bd.allowCaching = false;  
  16.         }  
  17.        <span style="color:#FF0000;"> BeanWrapper bw = new BeanWrapperImpl(existingBean);</span>  
  18.         initBeanWrapper(bw);  
  19.         populateBean(beanName, bd, bw);  
  20.         return initializeBean(beanName, existingBean, bd);  
  21.     }  

 

 

BeanWrapperImpl 继承了属性编辑注册功能

 

 

如何设置值 :

 

[java] view plain copy
 
  1. @Override  
  2.     public void setPropertyValue(String propertyName, Object value) throws BeansException {  
  3.         BeanWrapperImpl nestedBw;  
  4.         try {  
  5.            //获取嵌套的属性, like map[my.key], 没有嵌套属性就返回自己  
  6.             nestedBw = getBeanWrapperForPropertyPath(propertyName);  
  7.         }  
  8.         catch (NotReadablePropertyException ex) {  
  9.             throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,  
  10.                     "Nested property in path '" + propertyName + "' does not exist", ex);  
  11.         }  
  12.         PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));  
  13.         nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value));  
  14.     }  


看下面具体方法的实现

 

 

[java] view plain copy
 
  1. /** 
  2.      * Recursively navigate to return a BeanWrapper for the nested property path. 
  3.      * @param propertyPath property property path, which may be nested 
  4.      * @return a BeanWrapper for the target bean 
  5.      */  
  6.     protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) {  
  7.         int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);  
  8.         // Handle nested properties recursively.  
  9.         if (pos > -1) {  
  10.             String nestedProperty = propertyPath.substring(0, pos);  
  11.             String nestedPath = propertyPath.substring(pos + 1);  
  12.                         //递归获取最后一个属性  
  13.                         BeanWrapperImpl nestedBw = getNestedBeanWrapper(nestedProperty);  
  14.             return nestedBw.getBeanWrapperForPropertyPath(nestedPath);  
  15.         }  
  16.         else {  
  17.             return this;  
  18.         }  
  19.     }  



 

 

 

自己实现了个小例子:

 

[java] view plain copy
 
  1. public class HelloWorld {  
  2.       
  3.     private String msg = null;  
  4.     private Date date = null;  
  5.     public String getMsg() {  
  6.         return msg;  
  7.     }  
  8.     public void setMsg(String msg) {  
  9.         this.msg = msg;  
  10.     }  
  11.     public Date getDate() {  
  12.         return date;  
  13.     }  
  14.     public void setDate(Date date) {  
  15.         this.date = date;  
  16.     }  
  17.   
  18. }  
  19.   
  20. package com.sunkey.test;  
  21.   
  22. public class Pepole {  
  23.   
  24.     private String name;  
  25.       
  26.     private int sex;  
  27.       
  28.     private HelloWorld helloWorld;  
  29.   
  30.     public String getName() {  
  31.         return name;  
  32.     }  
  33.   
  34.     public void setName(String name) {  
  35.         this.name = name;  
  36.     }  
  37.   
  38.     public int getSex() {  
  39.         return sex;  
  40.     }  
  41.   
  42.     public void setSex(int sex) {  
  43.         this.sex = sex;  
  44.     }  
  45.   
  46.     public HelloWorld getHelloWorld() {  
  47.         return helloWorld;  
  48.     }  
  49.   
  50.     public void setHelloWorld(HelloWorld helloWorld) {  
  51.         this.helloWorld = helloWorld;  
  52.     }  
  53.       
  54. }  


测试代码:

 

 

[java] view plain copy
 
    1.  @Test  
    2.     public void testBeanWapper() throws InstantiationException, IllegalAccessException, ClassNotFoundException {  
    3.         Object obj = Class.forName("com.sunkey.test.HelloWorld").newInstance();  
    4.         BeanWrapper bw = new BeanWrapperImpl(obj);  
    5.         bw.setPropertyValue("msg", "HellowWorld");  
    6.         bw.setPropertyValue("date", new Date());  
    7.         System.out.println(bw.getPropertyValue("date") + "\n" + bw.getPropertyValue("msg"));  
    8.     }  
    9.   
    10.     @Test  
    11.     public void testNestedBeanWapper() throws InstantiationException, IllegalAccessException, ClassNotFoundException {  
    12.         Object obj = Class.forName("com.sunkey.test.HelloWorld").newInstance();  
    13.         BeanWrapper bw = new BeanWrapperImpl(obj);  
    14.         bw.setPropertyValue("msg", "HellowWorld");  
    15.         bw.setPropertyValue("date", new Date());  
    16.         Object objP = Class.forName("com.sunkey.test.Pepole").newInstance();  
    17.         BeanWrapper pbw = new BeanWrapperImpl(objP);  
    18.         pbw.setPropertyValue("name", "jack");  
    19.         pbw.setPropertyValue("helloWorld", obj);  
    20.         System.out.println(pbw.getPropertyValue("name") + "\n" + pbw.getPropertyValue("helloWorld.msg"));  
    21.         pbw.setPropertyValue("helloWorld.msg", "HellowWorld修改过");  
    22.         System.out.println(pbw.getPropertyValue("name") + "\n" + pbw.getPropertyValue("helloWorld.msg")); }