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

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

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

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

  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 继承了属性编辑注册功能

如何设置值 :

  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. }

看下面具体方法的实现

  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. }

自己实现了个小例子:

  1. public class HelloWorld {
  2. private String msg = null;
  3. private Date date = null;
  4. public String getMsg() {
  5. return msg;
  6. }
  7. public void setMsg(String msg) {
  8. this.msg = msg;
  9. }
  10. public Date getDate() {
  11. return date;
  12. }
  13. public void setDate(Date date) {
  14. this.date = date;
  15. }
  16. }
  17. package com.sunkey.test;
  18. public class Pepole {
  19. private String name;
  20. private int sex;
  21. private HelloWorld helloWorld;
  22. public String getName() {
  23. return name;
  24. }
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28. public int getSex() {
  29. return sex;
  30. }
  31. public void setSex(int sex) {
  32. this.sex = sex;
  33. }
  34. public HelloWorld getHelloWorld() {
  35. return helloWorld;
  36. }
  37. public void setHelloWorld(HelloWorld helloWorld) {
  38. this.helloWorld = helloWorld;
  39. }
  40. }

测试代码:

    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. @Test
    10. public void testNestedBeanWapper() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    11. Object obj = Class.forName("com.sunkey.test.HelloWorld").newInstance();
    12. BeanWrapper bw = new BeanWrapperImpl(obj);
    13. bw.setPropertyValue("msg", "HellowWorld");
    14. bw.setPropertyValue("date", new Date());
    15. Object objP = Class.forName("com.sunkey.test.Pepole").newInstance();
    16. BeanWrapper pbw = new BeanWrapperImpl(objP);
    17. pbw.setPropertyValue("name", "jack");
    18. pbw.setPropertyValue("helloWorld", obj);
    19. System.out.println(pbw.getPropertyValue("name") + "\n" + pbw.getPropertyValue("helloWorld.msg"));
    20. pbw.setPropertyValue("helloWorld.msg", "HellowWorld修改过");
    21. System.out.println(pbw.getPropertyValue("name") + "\n" + pbw.getPropertyValue("helloWorld.msg")); }

Spring BeanWrapper分析的更多相关文章

  1. Spring研磨分析、Quartz任务调度、Hibernate深入浅出系列文章笔记汇总

    Spring研磨分析.Quartz任务调度.Hibernate深入浅出系列文章笔记汇总 置顶2017年04月27日 10:46:45 阅读数:1213 这系列文章主要是对Spring.Quartz.H ...

  2. MyBatis整合Spring原理分析

    目录 MyBatis整合Spring原理分析 MapperScan的秘密 简单总结 假如不结合Spring框架,我们使用MyBatis时的一个典型使用方式如下: public class UserDa ...

  3. 深入浅出Spring(四) Spring实例分析

    上次的博文中 深入浅出Spring(二) IoC详解 和 深入浅出Spring(三) AOP详解中,我们分别介绍了一下Spring框架的两个核心一个是IoC,一个是AOP.接下来我们来做一个Sprin ...

  4. 【spring源代码分析】--Bean的解析与注冊

    接着上一节继续分析,DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法: protected void parseBeanDefini ...

  5. Spring AOP分析(1) -- 基本概念

    AOP全称是Aspect Oriented Programming,面向切面编程,是面向对象编程(OOP:Object Oriented Programming)的补充和完善.一般在系统中,OOP利用 ...

  6. Spring AOP分析(2) -- JdkDynamicAopProxy实现AOP

    上文介绍了代理类是由默认AOP代理工厂DefaultAopProxyFactory中createAopProxy方法产生的.如果代理对象是接口类型,则生成JdkDynamicAopProxy代理:否则 ...

  7. Spring Aop分析

    前言 上文讲述ioc框架的实现,本文开始讲述aop.在spring中aop也有3种配置方式,注解形式的我们先不讨论.我们先看看xml形式的配置方式. <aop:config> <ao ...

  8. Spring IOC分析

    前言 关于Spring,我想无需做太多的解释了.每个Java程序猿应该都使用过他.Spring的ioc和aop极大的方便了我们的开发,但是Spring又有着不好的一面,为了符合开闭原则,Spring的 ...

  9. [置顶] 深入浅出Spring(四) Spring实例分析

    上次的博文中 深入浅出Spring(二) IoC详解 和 深入浅出Spring(三) AOP详解中,我们分别介绍了一下Spring框架的两个核心一个是IoC,一个是AOP.接下来我们来做一个Sprin ...

随机推荐

  1. 【一天一道LeetCode】#24. Swap Nodes in Pairs

    一天一道LeetCode系列 (一)题目 Given a linked list, swap every two adjacent nodes and return its head. For exa ...

  2. Gradle 1.12用户指南翻译——第二十七章. Ear 插件

    其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...

  3. C/C++语言中NULL、'\0’和0的区别

    注:本文参考了http://blog.csdn.net/mylinx/article/details/6873253及书籍<征服C指针>([日]前桥和弥著). NULL.'\0'和0的值是 ...

  4. GCC/gcc/g++/CC/cc区别

    平常在Linux上经常会用到gcc或者g++来编译程序,但对这两者的理解也就停留在一个是用来编译C程序,另一个是用来编译C++程序的(请注意:这种说法是有问题的,待会改进). 1. GCC GCC,是 ...

  5. Android高通平台调试Camera驱动全纪录

    项目比较紧,3周内把一个带有外置ISP,MIPI数据通信,800万像素的camera从无驱动到实现客户全部需求. 1日 搭平台,建环境,编译内核,烧写代码. 我是一直在Window下搭个虚拟机登服务器 ...

  6. 二叉树(LeetCode) C++相关知识代码 系列1

    0.二叉树最大深度 原题目:Given a binary tree, find its minimum depth.The minimum depth is the number of nodes a ...

  7. 二叉树的序列化和反序列化(Java)

    请实现两个函数,分别用来序列化和反序列化二叉树 序列化就是将二叉树以字符串输出,反序列化:根据自己输出的字符串,构建二叉树. 这里先序遍历输出,且为了方便反序列化,各个节点","隔 ...

  8. JS核心笔记

    一.说明 JS权威指南文字用红色标出: JS高级程序设计用橙色标出; 自己加上的文字用粉红色标出: 其(一)-(九)为JS权指南,(十)为JS高级程序设计 二.记法结构 2.1字符集 Javascri ...

  9. ajax调用servlet

    1.利用myecilpse建立一个web项目 2.导入需要的包: commons-beanutils.jar commons-collections-3.1.jar       commons-lan ...

  10. Collections模块下的Counter

    class Counter(dict) 这个类是dict的子类,对哈希类型的项进行计数,元素被存储为字典的键,他们的计数将作为字典的键值. 主要介绍两个方法: 1.初始化方法:__init__(*ar ...