【死磕Spring】| Spring IoC容器:BeanFactory和ApplicationContext谁才是Spring IoC容器?

Spring IoC容器:BeanFactory和ApplicationContext谁才是Spring IoC容器?

  • 对于我们初学者来说,我们是不是在写Demo的时候经常这样写:

    • BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-injection.xml");
      
  • 其实,BeanFactory 和 ApplicationContext 同为IoC容器,而ApplicationContext是BeanFactory的子接口,所以上面的代码才会有效,不会报错。其实我们应该这样来书写才最为正确:

    • ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-injection.xml");
      
    • ApplicationContext 重写了 BeanFactory的方法,并扩充了许多BeanFactory所不具有的功能,例如:

      • 更容易整合AOP模块
      • 国际化
      • 事件
      • 应用于web,例如 WebApplicationContext IoC容器
    • 总之,BeanFactory提供Spring框架的基本配置和功能,而ApplicationContext在其基础上又实现了更多企业级需要的功能,它们都能管理IoC容器的对象。可以把ApplicationContext理解为BeanFactory的超集。

  • 那既然 ApplicationContext is BeanFactory,那下面这段代码为什么输出false呢?

    • public class DependencyInjectionDemo {
          public static void main(String[] args) {
          //1.配置 xml 文件
              //2.启动 Spring 应用上下文
              ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-injection.xml");
              UserRepository repository = applicationContext.getBean(UserRepository.class);
              whoIsIoCContainer(repository,applicationContext);
          }
          private static void whoIsIoCContainer(UserRepository userRepository,ApplicationContext applicationContext){
              System.out.println(userRepository.getBeanFactory() == applicationContext);
          }
      }
      
    • 【死磕Spring】| Spring IoC容器:BeanFactory和ApplicationContext谁才是Spring IoC容器?
  • 这个问题,我们需要深入到源码中去分析了!

    • 这个阶段,我们先入为主,直接告诉大家 类的继承关系
    • 首先,我们直接定位到 AbstractRefreshableApplicationContext 这个类,然后给大家一幅图,来直观的感受一下ClassPathXmlApplicationContext和AbstractRefreshableApplicationContext中间类的继承关系
    • 【死磕Spring】| Spring IoC容器:BeanFactory和ApplicationContext谁才是Spring IoC容器?
    • 按照这样一个方式,我们找到了BeanFactory的真身,它其实就是我们前几节讲过的Spring内建依赖 DefaultListableBeanFactory
    • 而我们经常使用的 BeanFactory#getBean() 这样的功能, 其实底层实现是这样的:
      • 【死磕Spring】| Spring IoC容器:BeanFactory和ApplicationContext谁才是Spring IoC容器?
      • 继续深入底层,我们发现,获取的BeanFactory就是我们上面提到的 DefaultListableBeanFactory
      • 【死磕Spring】| Spring IoC容器:BeanFactory和ApplicationContext谁才是Spring IoC容器?
      • 【死磕Spring】| Spring IoC容器:BeanFactory和ApplicationContext谁才是Spring IoC容器?
    • 总结下来我们提到的 ApplicationContext is BeanFactory,它确实是对的,但为什么我们注入的BeanFactory和ApplicationContext不同呢?
      • 首先,无论是ApplicationContext还是BeanFactory,他们的getBean()功能都是通过获取DefaultListableBeanFactory然后通过这个BeanFactory来实现的依赖查找功能,DefaultListableBeanFactory也是BeanFactory的一个子接口,但它和ApplicationContext是完全不同的两个接口,它俩之间并没有继承关系,所以就会出现我们自己注入的BeanFactory和ClassPathXmlApplicationContext不同。
  • 最后总结一下,其实这样的实现模式可以类比为代理,一个类实现一个功能是通过代理对象来实现的。

上一篇:在Static方法中引用被@AutoWired修饰的属性,无法注入,报空指针异常、SpringBoot + Mybatis


下一篇:Spring源码之ApplicationContext