今天去观澜的平安大学,参加了后台开发技术的Spring培训。培训中讲师提了一个问题,如果要注入的属性没有setter方法,那么Spring会抛出什么错?大家一开始都任务是NoSuchMethodException,因为找不到对应的Setter方法么。但是结果是Spring自己封装的一个异常org.springframework.beans.NotWritablePropertyException

晚上到家后,我就看下Spring的源码,这个异常是怎么抛出的。这个异常是在org.springframework.beans.AbstractNestablePropertyAccessor类中抛出的,抛出异常的方法原型如下:

    protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException;

跟踪发现,Spring会去获取要注入类的基本信息,比如类中属性和方法。而Spring中获取这些方法直接使用了Java自带的BeanInfo一系列类,这些类位于java.beans包下,我原来都不知道Java已经自带了这些bean处理的方法。

获取BeanInfo

最简单的方法如下:

    BeanInfo beanInfo = Introspector.getBeanInfo(Test.class);

Introspector.getBeanInfo还有其他参数的方法,主要用来控制返回信息的多少。比如:

  1. BeanInfo beanInfo = Introspector.getBeanInfo(Test.class,Test.class.getSuperclass());

    第二个参数是stopClass,即停止查找的类,该类必须是Test类的父类,这样查找BeanInfo的时候就会在stopClass停止。最常见的比如,如果不给定第二个stopClass,那么继承自Object类的所有方法和属性也会在BeanInfo里,如果传入参数***Object.class***那么Object类的方法和属性就不会显示了。
    
  2. BeanInfo beanInfo = Introspector.getBeanInfo(Test.class,Introspector.IGNORE_ALL_BEANINFO);

    第二个是int类型的标志位,USE_ALL_BEANINFO使用可以发现的所有 BeanInfo 类,这个也是默认属性,IGNORE_IMMEDIATE_BEANINFO忽略与指定 beanClass 相关联的任何 BeanInfo,IGNORE_ALL_BEANINFO忽略与指定 beanClass 相关联的所有 BeanInfo 及其所有父类。
    

BeanInfo使用

BeanInfo里面有下面这几个重要的方法:

  1. PropertyDescriptor[] getPropertyDescriptors();

    获取bean属性,PropertyDescriptor可以获取属性名字(getName),获取该属性的Setter(getWriteMethod())和Getter(getReadMethod())方法。
  2. MethodDescriptor[] getMethodDescriptors();

    获取bean中所有的方法,包括上面提到的属性的Setter和Getter方法。
    

标签: none

添加新评论