写点什么

spring 系列之 IOC 容器实例化过程四

作者:王威07325
  • 2023-05-29
    上海
  • 本文字数:5068 字

    阅读完需:约 17 分钟

fresh 中的 prepareBeanFactory 方法

很好,过年期间订下的计划没有完成,我知道我有罪,但是过年这段期间是真的好好玩!!。我觉得好好玩个几天应该也不过分,哈哈哈!!最后希望看到这篇博客的小伙伴可以点点赞,编写不易。



prepareBeanFactory 方法负责对 BeanFactory 进行一些特征的设置工作,"特征"包含这么几个方面:


  1. BeanExpressionResolver

  2. PropertyEditorRegistrar

  3. 环境注入

  4. 依赖解析忽略

  5. bean 伪装

  6. LoadTimeWeaver

  7. 注册环境


在讲解这几个方面之前还是先贴上方法的代码:


protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {    // Tell the internal bean factory to use the context's class loader etc.    beanFactory.setBeanClassLoader(getClassLoader());    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }
// Register default environment beans. if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
复制代码

1.BeanExpressionResolver

此接口只有一个实现: StandardBeanExpressionResolver。接口只含有一个方法:


/**   * Evaluate the given value as an expression, if applicable;   * return the value as-is otherwise.   * @param value the value to check   * @param evalContext the evaluation context   * @return the resolved value (potentially the given value as-is)   * @throws BeansException if evaluation failed   */  Object evaluate(String value, BeanExpressionContext evalContext) throws BeansException;
复制代码


prepareBeanFactory 将一个此对象放入 BeanFactory:


beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
复制代码


StandardBeanExpressionResolver 对象内部有一个关键的成员: SpelExpressionParser,它的存在支撑着 Spring3.0 开始出现的 Spel 表达式功能。

2.PropertyEditorRegistrar

此接口用于向 Spring 注册 java.beans.PropertyEditor,只有一个方法:


/**   * Add a PropertyEditorRegistrar to be applied to all bean creation processes.   * <p>Such a registrar creates new PropertyEditor instances and registers them   * on the given registry, fresh for each bean creation attempt. This avoids   * the need for synchronization on custom editors; hence, it is generally   * preferable to use this method instead of {@link #registerCustomEditor}.   * @param registrar the PropertyEditorRegistrar to register   */  void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
复制代码


实现也只有一个: ResourceEditorRegistrar。


在编写 xml 配置时,我们设置的值都是字符串形式,所以在使用时肯定需要转为我们需要的类型,PropertyEditor 接口正是定义了这么个东西。


beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
复制代码


BeanFactory 也暴露了 registerCustomEditors 方法用以添加自定义的转换器,所以这个地方是组合模式的体现。


我们有两种方式可以添加自定义 PropertyEditor:


  • 通过 context.getBeanFactory().registerCustomEditor

  • 通过 Spring 配置文件:


<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">  <property name="customEditors">          <map>              <entry key="base.Cat" value="base.CatEditor" />       </map>  </property></bean>
复制代码

3.环境注入

在 Spring 中我们自己的 bean 可以通过实现 EnvironmentAware 等一系列 Aware 接口获取到 Spring 内部的一些对象。prepareBeanFactory:


/**   * Add a new BeanPostProcessor that will get applied to beans created   * by this factory. To be invoked during factory configuration.   * <p>Note: Post-processors submitted here will be applied in the order of   * registration; any ordering semantics expressed through implementing the   * {@link org.springframework.core.Ordered} interface will be ignored. Note   * that autodetected post-processors (e.g. as beans in an ApplicationContext)   * will always be applied after programmatically registered ones.   * @param beanPostProcessor the post-processor to register   */  void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
复制代码


ApplicationContextAwareProcessor 核心的 invokeAwareInterfaces 方法:


private void invokeAwareInterfaces(Object bean) {    if (bean instanceof Aware) {      if (bean instanceof EnvironmentAware) {        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());      }      if (bean instanceof EmbeddedValueResolverAware) {        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);      }      if (bean instanceof ResourceLoaderAware) {        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);      }      if (bean instanceof ApplicationEventPublisherAware) {        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);      }      if (bean instanceof MessageSourceAware) {        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);      }      if (bean instanceof ApplicationContextAware) {        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);      }    }  }
复制代码


此方法是在 bean 的初始化过程中被调用的:


@Override  public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {    AccessControlContext acc = null;
if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); }
if (acc != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareInterfaces(bean); return null; } }, acc); } else { //处理bean对象是否实现相关的aware接口 invokeAwareInterfaces(bean); }
return bean; }
复制代码

4.依赖解析忽略

此部分设置哪些接口在进行依赖注入的时候应该被忽略:


beanFactory.ignoreDependencyInterface(EnvironmentAware.class);    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
复制代码

5.bean 伪装

有些对象并不在 BeanFactory 中,但是我们依然想让它们可以被装配,这就需要伪装一下:


// BeanFactory interface not registered as resolvable type in a plain factory.    // MessageSource registered (and found for autowiring) as a bean.    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);    beanFactory.registerResolvableDependency(ResourceLoader.class, this);    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
复制代码


伪装关系保存在一个 Map<Class<?>, Object>里。

6.LoadTimeWeaver

如果配置了此 bean,那么:


// Detect a LoadTimeWeaver and prepare for weaving, if found.    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));      // Set a temporary ClassLoader for type matching.      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));    }
复制代码


这个东西具体是干什么的以后会进行相关的说明,这里先记得有这么个东西存在就行。

7.注册环境

// Register default environment beans.    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());    }    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());    }    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());    }
复制代码


没啥可讲的,需要注意的是 containsLocalBean 不会去父 BeanFactory 寻找。

发布于: 刚刚阅读数: 5
用户头像

王威07325

关注

还未添加个人签名 2021-12-29 加入

还未添加个人简介

评论

发布
暂无评论
spring系列之IOC容器实例化过程四_spring ioc_王威07325_InfoQ写作社区