前面分析了prepareBeanFactory的前面一段。主要的作用如下:

  • 为工厂设置类的加载器、表达式解析器、属性编辑器注册器等
  • 为工厂添加后处理器、要忽略的依赖接口
  • 在工厂中注册可解析的依赖
  • 在工厂中提前注册一些单例Bean

上一节的源码主要是分析了前面的两个;1:设置了PropertyEditorRegistrar,这个可以用来实现自定义数据类型的装换。2:设置了ApplicationContextAwareProcessor。这个接口主要是用来用户可以自己实现Aware接口,实现这个接口可以做到获取Spring内置的一些对象。接下来我们分析后面的一段:

  1. protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  2. // BeanFactory interface not registered as resolvable type in a plain factory.
  3. // MessageSource registered (and found for autowiring) as a bean.
  4. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  5. beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  6. beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  7. beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  8. // Register early post-processor for detecting inner beans as ApplicationListeners.
  9. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  10. // Detect a LoadTimeWeaver and prepare for weaving, if found.
  11. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
  12. beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
  13. // Set a temporary ClassLoader for type matching.
  14. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  15. }
  16. // Register default environment beans.
  17. if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
  18. beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
  19. }
  20. if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
  21. beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
  22. }
  23. if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
  24. beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
  25. }
  26. }

一、beanFactory.registerResolvableDependency方法

registerResolvableDependency()方法是声明在 ConfigurableListableBeanFactory接口中的在初始化IOC中的时候,在AbstractApplicationContext#prepareBeanFactory中被调用。该方法的作用如下:
Spring自动装配的时候如果一个接口有多个实现类,并且都已经放到IOC中去了,那么自动装配的时候就会出异常,因为spring不知道把哪个实现类注入进去,但是如果我们自定义一个类,然后实现BeanFactoryPostProcessor接口在该阶段调用这个方法,如果哪个地方要自动注入这个类型的对象的话,那么就注入进去我们指定的对象。
实战:定义 Component 接口

  1. public interface Component {}

然后创建两个Component的实现类,分别为 ComponentAImple 和 ComponentBImlp

  1. @Component
  2. public class ComponentAImple implements Component {
  3. private String mark = "a";
  4. }
  5. @Component
  6. public class ComponentBImple implements Component {
  7. private String mark = "b";
  8. }

创建一个junit单元测试类

  1. @RunWith(SpringRunner.class)
  2. @ContextConfiguration(classes = SpringTest2Config.class)
  3. public class TestSpring1 {
  4. @Autowired
  5. private Component component;
  6. @Test
  7. public void test(){
  8. }
  9. }

注入一个 component类型的对象。上面这个程序启动肯定是会报错的
原因:因为Component类型的对象有两个,而且都是由Spring管理的,Spring注入对象的时候发现了多个,它不知道应该注入哪个对象而抛出异常
09-Spring源码refresh-prepareBeanFactory-2 - 图1
可以使用 @Primary 注解,但是这个注解不在这里讨论
我们可以使用 registerResolvableDependency()方法来实现。创建一个 TestRegisterResolvableDependency 类,实现BeanFactoryPostProcessor接口 并放到IOC容器中

  1. @Component
  2. public class TestRegisterResolvableDependency implements BeanFactoryPostProcessor {
  3. @Override
  4. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  5. beanFactory.registerResolvableDependency(Component.class, new ComponentAImple());
  6. }
  7. }

注意beanFactory.registerResolvableDependency(Component.class, new ComponentAImple()); 方法,这行代码的意思是,当有其他类要注入 Component类型的对象时,就给他注入我们这里自己创建的 ComponentAImple对象。

可以参考文章:https://blog.csdn.net/yuge1123/article/details/106053857 这篇文章主要写的是beanFactory.registerResolvableDependency()方法的用法。


二、ApplicationListenerDetector

ApplicationListenerDetector是Spring中内置的BeanPostProcessor实现,主要是为了检测Spring容器中的的ApplicaiontListener,然后将其注册到Spring上下文中。

  1. @Override
  2. public Object postProcessAfterInitialization(Object bean, String beanName) {
  3. // 当上下文不为空时且该bean是ApplicationListener
  4. if (this.applicationContext != null && bean instanceof ApplicationListener) {
  5. // potentially not detected as a listener by getBeanNamesForType retrieval
  6. // 如果是单例,则将该bean注册至上下文中
  7. Boolean flag = this.singletonNames.get(beanName);
  8. if (Boolean.TRUE.equals(flag)) {
  9. // singleton bean (top-level or inner): register on the fly
  10. this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
  11. }
  12. else if (Boolean.FALSE.equals(flag)) {
  13. if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
  14. // inner bean with other scope - can't reliably process events
  15. logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
  16. "but is not reachable for event multicasting by its containing ApplicationContext " +
  17. "because it does not have singleton scope. Only top-level listener beans are allowed " +
  18. "to be of non-singleton scope.");
  19. }
  20. this.singletonNames.remove(beanName);
  21. }
  22. }
  23. return bean;
  24. }

ApplicationListenerDetector实现了实例化后进行后置处理的逻辑,主要就是检测ApplicationListener,然后将其加入Spring上下文中。

三、在工厂中提前注册一些单例Bean