「Spring」BeanFactory和ApplicationContext

168 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

1.1、BeanFactory

做什么的

接口本身只有关于bean的一些管理 但是Spring的核心功能

  • 控制反转
  • 依赖注入
  • 单例Bean的生命周期

都是由BeanFactory的子类进行管理的

DefaultListableBeanFactory

1、是什么? 默认的BeanFactory接口的实现类,其中可以对Bean的创建进行一系列管理 包括管理Bean的单例/多例、Bean的名称等等

2、如何使用? 默认在项目启动的时候会去调用将所有需要注册的类(有相关注解、在目标位置、使用目标代码格式等)注册到工厂中。注册方式类似下面的代码

    public static void main(String[] args) {
        //创建默认的BeanFactory对象
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        //使用类创建Definition对象
        AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(CoderymyDemoApplication.class).setScope("singleton").getBeanDefinition();
        //将Definition 对象加入BeanFactory
        defaultListableBeanFactory.registerBeanDefinition("kcCouponApplication", beanDefinition);
        for (String name:defaultListableBeanFactory.getBeanDefinitionNames()){
            System.out.println(name);
        }
    }

后处理器

补充BeanFactory的功能

  • 不会主动调用BeanFactory后处理器
  • 不会主动调用Bean后处理器
  • 不会主动初始化对象(单例)

是什么:基础的使用Definition注册到BeanFactory只是将Bean本身注册到了Spring池中。但是Spring还有其他的功能呢,比如我的类中的一些属性上标注了@Bean注解这些属性也需要注册进去呢;还有我的类方法中使用的一些对象是通过@Autowried注册进来的呢。

所以就需要后处理器来帮助进行一些其他辅助操作

  • BeanFactory后处理器

    BeanFactoryPostProcessor,可以用来处理注册进入的Bean其中的还有需要注册的对象

  • Bean 后处理器

    BeanPostProcessor,处理类似@Autowried@Value等注解的功能

        //将BeanFactory的后处理器加入到Bean的创建流程中
        defaultListableBeanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(defaultListableBeanFactory);
        });
        
        //将Bean的后处理器加入到Bean的创建流程中
        defaultListableBeanFactory.getBeansOfType(BeanPostProcessor.class).values().stream().forEach(defaultListableBeanFactory::addBeanPostProcessor);
​

1.2、ApplicationContext

应用上下文对象 除了BeanFactory的功能之外扩展的功能:

  • 资源对象管理classpath:xxxx
  • 环境数据管理xxxx.properties
  • 国际化(翻译浏览器):MessageSource
  • 发布事件
ConfigurableApplicationContext context = SpringApplication.run(KcCouponApplication.class, args);
//国际化
context.getMessage();
//静态资源文件
context.getResources();
//环境相关 系统环境变量、properties等
context.getEnvironment();
//发布事件(用于代码解耦合,和MQ逻辑差不多) 继承PublishEvent接口就是事件 使用@EventListener进行事件监听
context.publishEvent();

1、ClassPathXmlApplicationContext

基于类路径,也就是xxx.xml文件对资源文件的管理,也就是对xml的bean的解析并注入进去

<bean id="beanService"  class="cn.coderymy.Service.BeanService"/>

2、FilesSystemXmlApplication

基于磁盘路径的xml文件。也就是需要在注入的时候将整个路径全部输入

3、AnnotationConfigApplicationContext

基于Java类的配置类的实现

4、AnnotationConfigServletWebServerApplicationContext

基于Java类的servelet也就是web环境创建

1.3、两者的关系

ApplicationContext的一部分功能是继承自BeanFactory

ApplicationContext除了BeanFactory继承来的数据之外,还通过和其他的接口获取的数据进行组合并扩展BeanFactory的功能

从上述后处理器可以看出来BeanFactory并不会主动加载那些后处理器,这样的话功能就很单一了,只会扫描并将对象加入BeanFactory中。那么其他的Spring扩展功能都没有实现。

所以ApplicationContext实现BeanFactory的时候就实现了一些其他的逻辑信息