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")); }
Spring BeanWrapper分析的更多相关文章
- Spring研磨分析、Quartz任务调度、Hibernate深入浅出系列文章笔记汇总
Spring研磨分析.Quartz任务调度.Hibernate深入浅出系列文章笔记汇总 置顶2017年04月27日 10:46:45 阅读数:1213 这系列文章主要是对Spring.Quartz.H ...
- MyBatis整合Spring原理分析
目录 MyBatis整合Spring原理分析 MapperScan的秘密 简单总结 假如不结合Spring框架,我们使用MyBatis时的一个典型使用方式如下: public class UserDa ...
- 深入浅出Spring(四) Spring实例分析
上次的博文中 深入浅出Spring(二) IoC详解 和 深入浅出Spring(三) AOP详解中,我们分别介绍了一下Spring框架的两个核心一个是IoC,一个是AOP.接下来我们来做一个Sprin ...
- 【spring源代码分析】--Bean的解析与注冊
接着上一节继续分析,DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法: protected void parseBeanDefini ...
- Spring AOP分析(1) -- 基本概念
AOP全称是Aspect Oriented Programming,面向切面编程,是面向对象编程(OOP:Object Oriented Programming)的补充和完善.一般在系统中,OOP利用 ...
- Spring AOP分析(2) -- JdkDynamicAopProxy实现AOP
上文介绍了代理类是由默认AOP代理工厂DefaultAopProxyFactory中createAopProxy方法产生的.如果代理对象是接口类型,则生成JdkDynamicAopProxy代理:否则 ...
- Spring Aop分析
前言 上文讲述ioc框架的实现,本文开始讲述aop.在spring中aop也有3种配置方式,注解形式的我们先不讨论.我们先看看xml形式的配置方式. <aop:config> <ao ...
- Spring IOC分析
前言 关于Spring,我想无需做太多的解释了.每个Java程序猿应该都使用过他.Spring的ioc和aop极大的方便了我们的开发,但是Spring又有着不好的一面,为了符合开闭原则,Spring的 ...
- [置顶] 深入浅出Spring(四) Spring实例分析
上次的博文中 深入浅出Spring(二) IoC详解 和 深入浅出Spring(三) AOP详解中,我们分别介绍了一下Spring框架的两个核心一个是IoC,一个是AOP.接下来我们来做一个Sprin ...
随机推荐
- OC中的枚举类型
背景 一直对OC中的位移操作枚举不太理解,查找到两篇介绍OC中枚举的文章,觉得很不错. 什么是位移操作枚举呢? typedef NS_OPTIONS(NSUInteger, UIViewAutores ...
- node.js 抓取
http://blog.csdn.net/youyudehexie/article/details/11910465 http://www.tuicool.com/articles/z2YbAr ht ...
- Mongodb系列之--mongodb的启动与关闭
Mongodb的开启 默认启动: $ ./mongodb 默认数据保存路径:/data/db/ 默认端口:27017 修改默认路径: --dbpath $ ./mongdb --d ...
- 中国象棋游戏Chess(3) - 实现走棋规则
棋盘的绘制和走棋参看博文:中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制,中国象棋游戏Chess(2) - 走棋 现在重新整理之前写的代码,并且对于每个棋子的走棋规则都进行了限制,不像之前那 ...
- FineReport性能调优的一些办法
FineReport性能调优的基本思路,就要对应用服务器的内存大小进行合理的设置. 一般服务器默认的内存配置都比较小,在较大型的应用项目中,这点内存是不够的,因此需要加工使其调大. 各应用服务器的内存 ...
- StickyListHeaders的使用
我们知道在ios中字母的导航有悬停的效果,在android中,git上有大神实现了这种悬停的功能,我们只要将普通的Listview改为StickyListHeadersListView然后设置adap ...
- rails小重构:将图片加入产品Model
原先的产品product模式中存放的是图片的url,必须手动将图片存入指定目录中.现在略作改动,在数据库中新建一个pictures表,其设定如下: class CreatePictures < ...
- ruby读取源代码自身的一种方法
我们知道ruby中如果源代码中一行开头(必须在行的开头)有__END__标示,则表示下面的都是数据行,可以用IO对象DATA来访问这些行.但是如果我们用DATA.rewind一下的话,就可以将文件流指 ...
- React Native入门 认识Flexbox布局
Flexbox布局是由W3C在09年提出的在Web端取代CSS盒子模型的一种布局方式. ReactNative实现了Flexbox布局的大部分功能. Flexbox布局所使用的属性,基本可以分为两大类 ...
- Spring Boot 2.0系列文章(七):SpringApplication 深入探索
关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/04/30/springboot_SpringApplication/ 前言 在 Spring B ...