zoukankan      html  css  js  c++  java
  • 从源码角度来看BeanFactory和ApplicationContext的关系

    大家好,我是小黑,这是年前的最后一篇推文,提前祝大家新年快乐~~

    这次我们从源码角度来聊聊BeanFactoryApplicationContext的关系,讲一些网上文章不曾提到的点。

    官方描述

    先来看一下官方文档中关于BeanFactoryApplicationContext的描述。

    The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactoryinterface provides an advanced configuration mechanism capable of managing any type of object.ApplicationContextis a sub-interface ofBeanFactory. It adds:

    • Easier integration with Spring’s AOP features

    • Message resource handling (for use in internationalization)

    • Event publication

    • Application-layer specific contexts such as the WebApplicationContext for use in web applications.

    https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-beanfactory

    从官方文档可以了解到:

    BeanFactory接口提供了能够管理任何类型对象的高级配置机制。

    ApplicationContextBeanFactory的子接口,它增加了如下一些功能:

    • 更容易与 Spring 的 AOP 集成
    • 消息资源处理,用于国际化
    • 事件发布
    • 特定于应用程序层的上下文,如用于 web 应用程序的WebApplicationContext

    源码简析

    以下源码基于 Spring 5.0.13 版本。

    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
    		MessageSource, ApplicationEventPublisher, ResourcePatternResolver
    
    public interface ListableBeanFactory extends BeanFactory
    

    从源码可以证实到,ApplicationContext继承了BeanFactory

    @Configurable
    public class Main {
    
        @Autowired
        BeanFactory beanFactory;
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
            Main bean = context.getBean(Main.class);
            // false
            System.out.println(context == bean.beanFactory);
            context.close();
        }
    }
    

    AnnotationConfigApplicationContextApplicationContext的一个实现类,换而言之,AnnotationConfigApplicationContext也是BeanFactory的一个实现类。

    但是,运行上述代码,System.out.println(context == bean.beanFactory);的输出结果为false

    这是不是意味着,在容器中,ApplicationContextBeanFactory是两个不同的实例对象呢?

    BeanFactory 和 ApplicationContext

    AnnotationConfigApplicationContext中有一个getBeanFactory方法。

    准确来说,是org.springframework.context.support.AbstractApplicationContext#getBeanFactory

    @Configurable
    public class Main {
    
        @Autowired
        BeanFactory beanFactory;
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
            Main bean = context.getBean(Main.class);
            // false
            System.out.println(context == bean.beanFactory);
            // true
            System.out.println(context.getBeanFactory() == bean.beanFactory);
            context.close();
        }
    }
    

    AbstractApplicationContextApplicationContext的抽象实现。

    AnnotationConfigApplicationContext继承了GenericApplicationContext,而GenericApplicationContext又继承了AbstractApplicationContext

    image.png

    AbstractApplicationContext中,所有BeanFactory接口的实现,都是委托给了BeanFactory对象。

    // AbstractApplicationContext#getBean(java.lang.Class<T>, java.lang.Object...)
    public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
      assertBeanFactoryActive();
      return getBeanFactory().getBean(requiredType, args);
    }
    
    // AbstractApplicationContext#getBeanFactory
    public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
    

    getBeanFactory()是一个抽象方法用。

    GenericApplicationContext实现了该抽象方法:

    public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    
    	private final DefaultListableBeanFactory beanFactory;
    	...
    	public final ConfigurableListableBeanFactory getBeanFactory() {
    		return this.beanFactory;
    	}
     	...
    }
    

    总结

    ApplicationContextBeanFactory的子接口,但是ApplicationContext的实例对象和BeanFactory的实例对象并不是同一个。

    ApplicationContext的实现中,有一个成员变量DefaultListableBeanFactory beanFactory,所有和BeanFactory接口相关的功能都是委派给这个成员变量来实现的。

    ApplicationContext实现类中的beanFactory成员变量和容器中的BeanFactory才是同一个实例对象。

  • 相关阅读:
    【JAVA基础】private 的使用
    【nginx】配置文件(模块、反向代理、负载均衡、动静分离)
    【Nginx】命令行安装
    【UNIAPP】websocte实现,功能:指定房间聊天,匿名进入 功能,文字与图片
    【前端JS】input对象图片在线转base64
    【UNIAPP】上传视频,进度条的前台与后端
    【IO阻塞异步】协程使用异步,异步爬虫,异步数据库操作
    【装饰器】原理以及基础使用
    可编程网络DataPath 及XDP
    gitlab 代码协作流程
  • 原文地址:https://www.cnblogs.com/coderxiaohei/p/12191488.html
Copyright © 2011-2022 走看看