Spring Framework中BeanFactory与ApplicationContext的关系与区别

Java
244
0
0
2024-02-23
标签   Spring

介绍

BeanFactory

首先来看来自官方文档的描述:

The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object.

我们来翻译一下:

beans和context是Spring Framework的IoC容器的基础。BeanFactory接口提供了一种高级配置机制,能够管理任何类型的对象。

如何理解这段话:

IoC(Inversion of Control)是Spring Framework的核心设计思想:它将对象的创建、组装、管理交给容器(container),BeanFactory提供了访问IoC的接口,使得开发者可以更方便的使用Spring框架来实现控制和依赖注入。

引用Spring Framework API文档中的一段话:

The root interface for accessing a Spring bean container.

This is the basic client view of a bean container; further interfaces such as ListableBeanFactory and ConfigurableBeanFactory are available for specific purposes. This interface is implemented by objects that hold a number of bean definitions, each uniquely identified by a String name.

我们再来翻译一下:

BeanFactory是访问Spring bean容器的根接口。

这是bean容器的基本客户端视图;诸如ListableBeanFactoryConfigurableBeanFactory之类的接口可用于特定目的。

这个接口是由包含许多bean定义的对象实现的,每个bean定义由一个String名称唯一标识。

如何理解这段话呢?

  1. 在Spring中,Spring bean 容器负责管理和组织JavaBean对象,BeanFactory接口定义了访问这个容器的基本方法。
  2. BeanFactory提供了最基本的访问Bean的方法,而对于更高级的功能,如列举所有Bean、配置Bean工厂等,Spring提供了其他专门的接口,如ListableBeanFactoryConfigurableBeanFactory。这些接口扩展了BeanFactory,提供了更多的功能和配置选项。
  3. 在Spring中,Bean的定义包括了Bean的类、依赖关系、配置信息等。BeanFactory接口的实现类是Spring容器,它持有多个Bean的定义,并且每个Bean都通过一个唯一的字符串名称进行标识。通过这个名称,客户端代码可以从容器中获取相应的Bean。
ApplicationContext

来自官方对Application的一段描述:

In short, the BeanFactory provides the configuration framework and basic functionality, and the ApplicationContext adds more enterprise-specific functionality. The ApplicationContext is a complete superset of the BeanFactory.

这段话不难理解:

一句话来说,BeanFactory为Spring框架提供了基础的方法和配置,ApplicationContext增加了更多企业级的方法,ApplicationContextBeanFactory的超集。

继承关系

通过继承关系可以看到ApplicationContextBeanFactory的子接口,通过继承的特性可知:ApplicationContext具有BeanFactory的所有功能,并在其基础上进行扩展。

两者的区别

两者是如何加载、获取Bean的?
准备工作:

创建类MyBean

被注入的类:

/**
 * Author: 公众号:种棵代码技术树
 * Date:   2023/12/23
 */
public class MyBean {

    private String message;

    public MyBean() {
    }

    public MyBean(String message) {
        System.out.println("MyBean被实例化了");
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void showMessage() {
        System.out.println("Message: " + message);
    }
}

resource目录下创建目录:META-INF,新建文件:spring-config.xml

classpath:/META-INF/ 是一个常用的目录,特别是在Java项目中,用于存放元信息文件,如配置文件、资源文件等。

<?xml version="1.0" encoding="UTF-8"?>
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  https://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context
  https://www.springframework.org/schema/context/spring-context.xsd">


  	<bean id = "myBean" class="org.thinging.in.spring.ioc.overview.bean.MyBean">
      <property name="message" value="Hello, Spring!" />
    </bean>
	
</beans>
通过BeanFactory获取Bean
/**
 * Author: 公众号:种棵代码技术树
 * Date:   2023/12/23
 */
public class BeanFactoryExample {
    public static void main(String[] args) {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/spring-config.xml");
        MyBean myBean = (MyBean) beanFactory.getBean("myBean");
        myBean.showMessage();
    }
}

输出结果:

通过ApplictaionContext获取Bean
/**
 * Author: 公众号:种棵代码技术树
 * Date:   2023/12/23
 */
public class ApplicationContextExample {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/spring-config.xml");
        MyBean myBean = (MyBean) applicationContext.getBean("myBean");
        myBean.showMessage();
    }
}

输出结果:

两者都是通过配置文件加载的类,输出相同的结果,那么他们是不是同一个对象呢?

/**
 * Author: 公众号:种棵代码技术树
 * Date:   2023/12/23
 */
public class ApplicationContextExample {
    public static void main(String[] args) {
        //使用ApplicationContext
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
        MyBean applicationContextBean = (MyBean) applicationContext.getBean("myBean");
        applicationContextBean.showMessage();

        //使用BeanFactory
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
        MyBean beanFactoryBean = (MyBean) beanFactory.getBean("myBean");
        beanFactoryBean.showMessage();

        //比较两者的引用
        boolean flag = applicationContextBean == beanFactoryBean;
        System.out.println("两者是否为同一个对象:" + flag);
    }
}

以上说明两者的引用不是同一个对象。

官方文档中描述的区别

在Spring Framework官方文档中指出了ApplicationContext相较于BeanFactory增加了以下特性:

  • Easier integration with Spring’s AOP features
  • 通过ApplicationContext可以更好的集成AOP。
  • Message resource handling (for use in internationalization)
  • 更好的处理国际化
  • Event publication
  • 支持事件机制,Spring的事件机制允许一个组件发布事件,而其他组件可以监听并响应这些事件。
  • Application-layer specific contexts such as the WebApplicationContext for use in web applications.
  • Spring的上下文(ApplicationContext)是一个IoC容器,用于管理和组织应用程序中的组件(Beans)。不同类型的应用程序可能需要不同的上下文。例如,对于Web应用程序,Spring提供了WebApplicationContext,它在ApplicationContext的基础上添加了一些特定于Web的功能,如处理Web相关的Bean(例如控制器)、处理Web请求等。

总结

在Spring框架中,由Spring IoC容器管理的构成应用程序骨架的对象被称为"beans"。一个bean是由Spring IoC容器实例化、组装和管理的对象。从另一个角度看,一个bean也只是应用程序中的众多对象之一。Beans以及它们之间的依赖关系都体现在容器所使用的配置元数据中。

  1. Bean: 由Spring IoC容器管理的对象,通过容器进行实例化、组装和生命周期管理。Beans的配置信息被反映在Spring IoC容器的配置元数据中。
  2. ApplicationContext: 是BeanFactory的超集,提供了更多的企业级功能。ApplicationContext是Spring IoC容器的一种,负责加载、实例化、配置和管理beans。

后续内容文章持续更新中…

近期发布。