【Spring 笔记】BeanWrapper 相关整理

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

1. 概述

  • 实例化 Bean 阶段,从 BeanDefinition 得到的是 BeanWrapper 实例,是一个从 BeanDefinition 到 Bean 的中间对象,一般情况下,不会在实际项目中用到它。
  • BeanWrapper 是 Spring 框架中重要的组件类,相当于一个代理类。
  • 在 Bean 实例被 InstantiationStrategy 创建出来后,Spring 容器会将 Bean 实例通过 BeanWrapper 包裹。

2. 原理

// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
......

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    Class beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    } else if (mbd.getFactoryMethodName() != null) {
        return this.instantiateUsingFactoryMethod(beanName, mbd, args);
    } else {
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized(mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }

        if (resolved) {
            return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
        } else {
            Constructor[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
            return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args) ? this.instantiateBean(beanName, mbd) : this.autowireConstructor(beanName, mbd, ctors, args);
        }
    }
}

// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    return AbstractAutowireCapableBeanFactory.this.getInstantiationStrategy().instantiate(mbd, beanName, AbstractAutowireCapableBeanFactory.this);
                }
            }, this.getAccessControlContext());
        } else {
            beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);
        }

        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        this.initBeanWrapper(bw);
        return bw;
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", var6);
    }
}

// BeanWrapperImpl.java
public BeanWrapperImpl(Object object) {
    super(object);
}

protected AbstractNestablePropertyAccessor(Object object) {
    registerDefaultEditors();
    setWrappedInstance(object);
}
 
 
  • BeanWrapper 主要继承三个核心接口 PropertyAccessorPropertyEditorRegistryTypeConverter
【Spring 笔记】BeanWrapper 相关整理_第1张图片
BeanWrapper 体系

PropertyAccessor

  • 可以访问属性的通用型接口(例如对象的 bean 属性或者对象中的字段),作为 BeanWrapper 的基础接口。
// PropertyAccessor.java
public interface PropertyAccessor {

    String NESTED_PROPERTY_SEPARATOR = ".";
    char NESTED_PROPERTY_SEPARATOR_CHAR = '.';

    String PROPERTY_KEY_PREFIX = "[";
    char PROPERTY_KEY_PREFIX_CHAR = '[';

    String PROPERTY_KEY_SUFFIX = "]";
    char PROPERTY_KEY_SUFFIX_CHAR = ']';

    boolean isReadableProperty(String propertyName);

    boolean isWritableProperty(String propertyName);

    Class getPropertyType(String propertyName) throws BeansException;
    TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;
    Object getPropertyValue(String propertyName) throws BeansException;

    void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException;
    void setPropertyValue(PropertyValue pv) throws BeansException;
    void setPropertyValues(Map map) throws BeansException;
    void setPropertyValues(PropertyValues pvs) throws BeansException;
    void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown)
    throws BeansException;
    void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
    throws BeansException;

}
  • 主要分为 4 类方法。
方法 说明
isReadableProperty() 判断指定 property 是否可读,是否包含 getter 方法。
isWritableProperty() 判断指定 property 是否可写,是否包含 setter 方法。
getPropertyType() 获取指定 propertyName 的类型。
setPropertyValue() 设置指定 propertyValue。

PropertyEditorRegistry

  • 用于注册 JavaBean 的 PropertyEditors,对 PropertyEditorRegistrar 起核心作用的中心接口。由 BeanWrapper 扩展,BeanWrapperImplDataBinder 实现。
// PropertyEditorRegistry.java
public interface PropertyEditorRegistry {

    void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor);

    void registerCustomEditor(@Nullable Class requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor);

    @Nullable
    PropertyEditor findCustomEditor(@Nullable Class requiredType, @Nullable String propertyPath);

}
  • 根据接口提供的方法,PropertyEditorRegistry 用于 PropertyEditor 的注册和发现,PropertyEditor 是 Java 内省接口,用于改变指定 property 属性的类型。

TypeConverter

  • 定义类型转换的接口,通常与 PropertyEditorRegistry 接口一起实现(但不是必须)
  • Spring 3 后,不再采用 PropertyEditors 类作为 Spring 默认的类型转换接口,而是采用 ConversionService 体系。
    • ConversionService 是线程安全的,所以在 Spring 3 后,如果选择的类型转换器是 ConversionService 那么 TypeConverters 是线程安全的。
    • 如果选择的是 PropertyEditors,则是线程不安全的。
// TypeConverter.java
public interface TypeConverter {

     T convertIfNecessary(Object value, Class requiredType) throws TypeMismatchException;
     T convertIfNecessary(Object value, Class requiredType, MethodParameter methodParam)
            throws TypeMismatchException;
     T convertIfNecessary(Object value, Class requiredType, Field field)
            throws TypeMismatchException;

}

  • BeanWrapper 继承了上述三个接口,所以可以作为 属性编辑器属性编辑器注册表类型转换器 使用。
  • BeanWrapper 除了继承 ConfigurablePropertyAccessor 接口以外,还集成了 Spring 的 ConversionService 类型转换体系。
// ConfigurablePropertyAccessor.java
public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter {

    void setConversionService(@Nullable ConversionService conversionService);

    @Nullable
    ConversionService getConversionService();
......
}

BeanWrapper

  • 一般不会直接使用,而是通过 BeanFactory 或者 DataBinder 隐式使用。
  • 它提供分析和操作标准 JavaBeans 的操作:获取和设置属性值、获取属性描述符以及查询属性的可读性/可写性的能力。
// BeanWrapper.java
public interface BeanWrapper extends ConfigurablePropertyAccessor {

    void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
    int getAutoGrowCollectionLimit();

    Object getWrappedInstance();
    Class getWrappedClass();

    PropertyDescriptor[] getPropertyDescriptors();
    PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;

}
方法 说明
getWrappedInstance() 获取包装对象的实例。
getWrappedClass() 获取包装对象的类型。
getPropertyDescriptors() 获取包装对象所有属性的 PropertyDescriptor 就是这个属性的上下文。
getPropertyDescriptor(String propertyName) 获取包装对象指定属性的上下文。

BeanWrapperImpl

  • BeanWrapper 接口的默认实现,用于对 Bean 的包装,实现接口所定义的功能。

你可能感兴趣的:(【Spring 笔记】BeanWrapper 相关整理)