AbstractApplicationContext类refresh()方法中的第三个调用方法prepareBeanFactory()的跟踪。

  1. @Override
  2. public void refresh() throws BeansException, IllegalStateException {
  3. synchronized (this.startupShutdownMonitor) {
  4. ...
  5. // Prepare the bean factory for use in this context.
  6. // 准备在上下文中bean factory的使用
  7. prepareBeanFactory(beanFactory);
  8. ···
  9. }
  • 为工厂设置类的加载器、表达式解析器、属性编辑器注册器等
  • 为工厂添加后处理器、要忽略的依赖接口
  • 在工厂中注册可解析的依赖
  • 在工厂中提前注册一些单例Bean ```java /**
  • Configure the factory’s standard context characteristics,
  • such as the context’s ClassLoader and post-processors. *
  • 配置工厂的标准上下文特征,比如上下文的ClassLoader和post-processors */ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //告知内部的bean工厂,使用上下文的类加载器 beanFactory.setBeanClassLoader(getClassLoader());

    //设置bean表达式解析器, //StandardBeanExpressionResolver内部expressionParser属性默认SpelExpressionParser类型 //spel = spring el表达式 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

    //将ResourceEditorRegistrar实例添加到工厂的propertyEditorRegistrars属性中, //propertyEditorRegistrars是一个LinkedHashSet,里面的元素将会应用到工厂bean中 //ResourceEditorRegistrar持有上下文和environment的引用 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 使用上下文回调配置bean 工厂 //在工厂的beanPostProcessor属性中添加处理器,beanPostProcessor是一个ArrayList beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    //在工厂的ignoredDependencyInterfaces属性中添加Aware系列接口, //ignoredDependencyInterfaces是一个HashSet beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

    // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean.

    // 在普通的工厂中,BeanFactory接口并没有按照resolvable类型进行注册 // MessageSource被注册成一个Bean(并被自动注入)

    //BeanFactory.class为key,beanFactory为value放入到了beanFactory的resolvableDependencies属性中 //resolvableDependencies是一个ConcurrentHashMap,映射依赖类型和对应的被注入的value //这样的话BeanFactory/ApplicationContext虽然没有以bean的方式被定义在工厂中, //但是也能够支持自动注入,因为他处于resolvableDependencies属性中 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);

    //再将上下文的一些接口与上下文本身做映射,一一放入到resolvableDependencies中 beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Detect a LoadTimeWeaver and prepare for weaving, if found. // 检测LoadTimeWeaver,如果有就准备织入 //1.跟踪进入,浅看下containsBean方法 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {

    1. //如果有LoadTimeWeaver,加入bean后处理器
    2. beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    3. // Set a temporary ClassLoader for type matching.
    4. // 为匹配类型设置一个临时的ClassLoader
    5. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));

    }

    // Register default environment beans. // 注册默认的environment beans

    // 判断目前这个bean工厂中是否包含指定name的bean,忽略父工厂 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {

    1. //虽然XmlWebApplicationContext中持有默认实现的StandardServletEnvironment
    2. //但是没有注册到beanFactory中,通过getEnvironment方法拿到持有的引用
    3. //2.注册environment单例
    4. beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());

    } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {

    1. //注册systemProperties单例
    2. beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());

    } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {

    1. //注册systemEnvironment单例
    2. beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());

    } }

    1. <a name="IVQEs"></a>
    2. ## 一、 增加SPEL语言的支持
    3. Spring 表达式语言全称为 “Spring Expression Language”,缩写为 “SpEL”,类似于Struts 2x 中使用的OGNL表达式语言,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等, 并且能与Spring功能完美整合,比如能用 来配置bean定义。SpEL是单独模块,只依赖于core 模块,不依赖于其他模块,可以单独使用。<br />SpEL使用#{...}为定界符,所有在花括号中的字符都将被认为是SpEL,使用格式如下:
    4. ```xml
    5. <bean id = "saxophone" value = "com.xxx.xxx.Xxx"/>
    6. <bean >
    7. <property name="instrument" value="#{saxophone}"/>
    8. <bean/>

    相当于:

    1. <bean id = "saxophone" value = "com.xxx.xxx.Xxx"/>
    2. <bean >
    3. <property name="instrument" ref="saxophone"/>
    4. <bean/>

    当然,上面只是列举了其中最简单的使用方式,SPEL功能非常强大,使用好可以大大提高开发效率,这里只为唤起读者的记忆来帮助我们理解源码,有兴趣的读者可以进一步深入研究。

在源码中通过代码beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver())注册语言解析器,就可以对SPEL进行解析了,那么在注册解析器后 Spring 又是在什么时候调用这个解析器进行解析呢?

之前我们讲解过 Spring 在 bean 进行初始化的时候会有属性填充的一步,而在这一步中 Spring 会调用AbstractAutowireCapableBeanFactory类的 applyPropertyValues 函数来完成功能。就在这个函数中,会通过构造 BeanDefinitionValueResolver类型实例 valueResolver 来进行属性值的解析。同时,也是在这个步骤中一般通过 AbstractBeanFactory中的evaluateBeanDefinitionString 方法去完成 SPEL 的解析。

二、增加属性注册编辑器

JavaBean API 中提供了这样一个接口:java.beans.PropertyEditor,该接口提供了将字符串值(String类型)映射为非String类型的方法。它便是传说中的属性编辑器。通过实现该接口,用户可以编写自定义属性编辑器,以将spring配置文件中的字符串转换成相应的对象注入。

  1. 但该接口有12个方法,如果用户要实现该接口编写自定义的属性编辑器会比较麻烦。幸运的是有一个好用的这个接口的实现类:`java.beans.PropertyEditorSupport`,我们可以继承这个实现类,覆写其中的`setAsText(String value)`方法,来实现我们的自定义属性编辑器。[

](https://blog.51cto.com/xiannenglin/435814)
配置属性自定义转换器可以参考:
10-Spring-配置属性自定义转换

Spring提供了一个配置类CustomEditorConfigurer,可以将自定义的属性编辑器注入到Spring中。此类实现了BeanFactoryPostProcessor接口,BeanFactoryPostProcessor可以在Bean实例化之前,往Spring容器中注入其他Bean。
image.png

从上面的CustomEditorConfigurer继承关系图可以看出,CustomEditorConfigurer实现了BeanFactoryPostProcessor接口。BeanFactoryPostProcessor是BeanFactory的后置处理器(BeanFactoryPostProcessor能定制和修改BeanFactory的内容,如覆盖或添加属性)。在BeanFactory标准初始化之后调用,这时所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建(即在Spring源码中refresh方法中的**invokeBeanFactoryPostProcessors**_**(**_**beanFactory**_**)**_**;**这个方法处理的是 实现BeanFactoryPostProcessor 接口的 Bean)。

理清楚BeanFactoryPostProcessor的功能作用后,下面进行分析CustomEditorConfigurer的工作原理。

  1. @Override
  2. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  3. if (this.propertyEditorRegistrars != null) {
  4. for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
  5. beanFactory.addPropertyEditorRegistrar(propertyEditorRegistrar);
  6. }
  7. }
  8. if (this.customEditors != null) {
  9. this.customEditors.forEach(beanFactory::registerCustomEditor);
  10. }
  11. }

CustomEditorConfigurer,它是一个特殊的BeanFactoryPostProcessor,可以将自定义的PropertyEditor或者PropertyEditorRegistrar实现存入其内部的customEditors和propertyEditorRegistrars属性中,启动项目之后,它的postProcessBeanFactory方法会在所有普通bean实例化和初始化之前(创建BeanWrapper之前)调用beanFactory来将这些PropertyEditor和propertyEditorRegistrars注册到AbstractBeanFactory的customEditors和propertyEditorRegistrars缓存。

基于以上的配置,在Spring bean对应的BeanWrapper初始化时,会自动从AbstractBeanFactory的customEditors和propertyEditorRegistrars缓存中将自定义的PropertyEditor注册到自己内部(位于AbstractBeanFactory#initBeanWrapper方法中),之后被BeanWrapper用于创建和填充 Bean 实例的类型转换。

但是请注意,这种配置不适用于Spring MVC的数据绑定,因为DataBinder默认不会查找这里注册到AbstractBeanFactory中的customEditors和propertyEditorRegistrars缓存,数据绑定时需要的自定义Editor必须在org.springframework.validation.DataBinder中手动注册(通过Spring MVC的@InitBinder方法)。

三、 添加 ApplicationContextAwareProcessor 处理器

了解了属性编辑器的使用后,接下来我们继续通过AbstractApplicationContextprepareBeanFactory 方法的主线来进行函数跟踪。对于 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))其实主要目的就是注册个 BeanPostProcessor,而真正的逻辑还是在ApplicationContextAwareProcessor中。
ApplicationContextAwareProcessor 实现BeanPostProcessor 接口,我们回顾下之前讲过的内容,在bean实例化的时候,也就是Spring激活bean的init-method的前后,会调用BeanPostProcessorpostProcessBeforelnitialization 方法和postProcessAfterlnitialization 方法。问样,对于ApplicationContextAwareProcessor我们也关心这两个方法。对于postProcessAfterlnitialization方法,在ApplicationContextAwareProcessor中并没有做过多逻辑处理。

  1. @Override
  2. public Object postProcessAfterInitialization(Object bean, String beanName) {
  3. return bean;
  4. }

那么,我们重点看一下postProcessBeforelnitialization 方法。

  1. @Override
  2. @Nullable
  3. public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
  4. AccessControlContext acc = null;
  5. // 省略代码....
  6. else {
  7. // 在postProcessBeforeInitialization调用invokeAware接口
  8. invokeAwareInterfaces(bean);
  9. }
  10. return bean;
  11. }
  12. private void invokeAwareInterfaces(Object bean) {
  13. if (bean instanceof Aware) {
  14. if (bean instanceof EnvironmentAware) {
  15. ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
  16. }
  17. if (bean instanceof EmbeddedValueResolverAware) {
  18. ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
  19. }
  20. if (bean instanceof ResourceLoaderAware) {
  21. ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
  22. }
  23. if (bean instanceof ApplicationEventPublisherAware) {
  24. ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
  25. }
  26. if (bean instanceof MessageSourceAware) {
  27. ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
  28. }
  29. if (bean instanceof ApplicationContextAware) {
  30. ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
  31. }
  32. }
  33. }

四. 设置忽略依赖

当Spring 将ApplicationContextAwareProcessor注册后,那么在invokeAwarelnterfaces方法中间接调用的 Aware 类已经不是普通的 bean 了,如 ResourceLoaderAware、ApplicationEventPublisher Aware等,那么当然需要在Spring做bean的依赖注入的时候忽略它们。而ignoreDependencylnterfece的作用正是在此。prepareBeanFactory方法中就有如下代码来禁止Environment或者ApplicationContext通过Autowired等方式获取

参考

https://www.cnblogs.com/warehouse/p/9387668.html