1、Spirng在生命周期里关于Bean的处理大概可以分为下面几步:
1)加载Bean定义(从xml或者从@Import等)
2)处理BeanFactoryPostProcessor,可修改BeanDefinition属性
3)实例化Bean
4)处理Bean的property注入
5)处理BeanPostProcessor,可修改实例化的Bean的属性值(@Value注入Bean的属性值是通过它)
而当我们在声明了<context:property-placeholder location="classpath:config.properties"/>标签之后,即声明了一个配置型bean交给Spring容器进行管理,即PropertyPlaceholderConfigurer类。我们先看一下这个类的继承结构。
2、自定义BeanFactoryPostProcessor(bean implements BeanFactoryPostProcessor),创建StringValueResolver对象,自定义String变量的值解析方法resolveStringValue(String strVal),将StringValueResolver对象添加到ConfigurableListableBeanFactory beanFactoryToProcess对象的embeddedValueResolvers列表中
3、注解修饰的类的实例对象是通过AbstractAutowireCapableBeanFactory的doCreateBean方法实例化的,然后由AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法注入属性值(element.inject() -> beanFactory.resolveDependency() -> resolveEmbeddedValue() -> 遍历embeddedValueResolvers列表,执行resolver.resolveStringValue() -> 自定义的StringValueResolver对象的resolveStringValue方法),至此,完成自定义属性值注入的逻辑。
4、通常设置spring配置文件的方式如下
如引文中所说,使用的是PropertyPlaceholderConfigurer类,主要流程如下
PropertyResourceConfigurer主流程中的三个方法,第一步已经执行完毕,加载了配置的properties文件,第二步是spring自己的默认实现,将非空的key对应的value放入Properties中,第三步则该由子类各自实现了,将BeanFactory与Properties进行统一操作。这时候我们看我们直接声明的派生类PropertyPlaceholderConfigurer。
PlaceHolderResolvingStringValueResolver就是解析properties文件中key-value键值对的类,可以自定义的,需要通过BeanFactoryPostProcessor添加到BeanFactory中的resolvers列表中。
引文中解释第2步是在对实例注入value值,实际测试发现并不是,并没有注入值(BeanFactoryPostProcessor可以修改BeanDefinition定义,不会修改Bean实例的值,因为此时并未实例化Bean);另外也测试了下是不是在为类成员变量注入值,也不是!所以对这一点比还是较迷惑,待确认!
第4步则是在将解析properties文件中key-value键值对的实例对象添加到BeanFactory中的resolvers列表中,会在实例化Bean之后调用AutowiredAnnotationBeanPostProcessor类的postProcessPropertyValues方法中被调用。