📜  Spring – BeanFactory 和 ApplicationContext 的区别

📅  最后修改于: 2022-05-13 01:55:23.005000             🧑  作者: Mango

Spring – BeanFactory 和 ApplicationContext 的区别

Spring 是最流行的Java EE 框架之一。它是一个开源轻量级框架,允许Java EE 开发人员构建简单、可靠和可扩展的企业应用程序。它提供了面向方面的编程。它为所有通用和中间件服务提供支持,主要侧重于提供各种方式来帮助您管理业务对象。它是一个模块化框架,其中所有模块都是根据称为“依赖注入”的概念设计的。

依赖注入:依赖注入是一种设计模式,它允许spring容器将对象“注入”到其他对象或依赖项中。简单来说,创建对象和管理 Spring 组件的控制由 Spring 容器负责。

弹簧容器

Spring Framework 提供了两个最基本和最重要的包,它们是org.springframework.beansorg.springframework.context包。这些包中的代码为 Spring 的控制反转/依赖注入特性提供了基础。 Spring 容器负责创建 bean 对象并将它们注入到类中。这两个容器是,

  1. BeanFactory(I) – 在 org.springframework.beans.factory 包中可用。
  2. ApplicationContext(I) – 在 rg.springframework.context 包中可用。

BeanFactory 接口

这是访问 Spring bean 容器的根接口。它是实例化、配置和管理大量 bean 的实际容器。这些 bean 相互协作,因此它们之间存在依赖关系。这些依赖关系反映在 BeanFactory 使用的配置数据中。该接口由包含许多 bean 定义的对象实现,每个定义由一个字符串名称唯一标识。这个 BeanFactory 最常用的实现类是org.springframework.beans.factory.xml 包中的XmlBeanFactory

示例代码:

Java
ClassPathResource resource = new ClassPathResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);


Java
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");


XML


Java
@Autowired
private String name;


Java
// create BeanFactory
ConfigurableBeanFactory factory = new ConfigurableBeanFactory(resource);
 
// register needed BeanPostProcessors
HelloBeanPostProcessor bpp = new HelloBeanPostProcessor();
factory.addBeanPostProcessor(bpp);


Java
public class WelcomeBean {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String welcomeMsg() {
        return "Welcome " + name;
    }
 
    public void initializeBean() {
        System.out.println("Welcome Bean is initialized!!");
    }
 
    public void destroyBean() {
        System.out.println("Welcome Bean is destroyed!!");
    }
 
}


XML

 

 
    
        
    
 


Java
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
 
import com.geeks.beans.WelcomeBean;
 
public class WelcomeBeanTest {
    public static void main(String[] args) {
 
        ClassPathResource res = new ClassPathResource("beans.xml");
        XmlBeanFactory factory = new XmlBeanFactory(res);
        System.out.println("Before getBean() method");
 
        WelcomeBean welcome = (WelcomeBean) factory.getBean("welcomeBean");
        System.out.println(welcome.welcomeMsg());
        ((XmlBeanFactory)factory).destroySingletons();
 
    }
 
}


Java
public class HelloBean {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String helloMsg() {
        return "Hello " + name;
    }
 
    public void initializeBean() {
        System.out.println("Hello Bean is initialized!!");
    }
 
    public void destroyBean() {
        System.out.println("Hello Bean is destroyed!!");
    }
 
}


Java
public class WelcomeBean {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String welcomeMsg() {
        return "Welcome " + name;
    }
 
    public void initializeBean() {
        System.out.println("Welcome Bean is initialized!!");
    }
 
    public void destroyBean() {
        System.out.println("Welcome Bean is destroyed!!");
    }
 
}


Java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.geeks.beans.HelloBean;
 
public class HelloBeanTest {
 
    public static void main(String[] args) {
 
        ApplicationContext con = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("Before getBean() method");
        HelloBean hello = (HelloBean) con.getBean("helloBean");
 
        System.out.println(hello.helloMsg());
        ((ClassPathXmlApplicationContext) con).close();
 
    }
 
}


Java
String getMessage (String code, Object[] args, String default, Locale loc)



ApplicationContext 接口

该接口是在 BeanFactory 接口之上设计的。 ApplicationContext 接口是高级容器,它以更加面向框架的风格增强了 BeanFactory 的功能。虽然 BeanFactory 提供管理和操作 bean 的基本功能,通常以编程方式,但 ApplicationContext 提供额外的功能,如 MessageSource、访问资源、事件传播到 bean、加载多个(分层)上下文等。有很多实现类可以使用诸如ClassPathXmlApplicationContextFileSystemXmlApplicationContextAnnotationConfigWebApplicationContext等。

示例代码:

Java

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");


接口层次结构

下面是 BeanFactory(I) 和 ApplicationContext(I) 的层次结构以及它们的一些实现类。

层次结构

层次结构

差异表

BeanFactory

ApplicationContext

It is a fundamental container that provides the basic functionality for managing beans.It is an advanced container that extends the BeanFactory that provides all basic functionality and adds some advanced features.
It is suitable to build standalone applications.It is suitable to build Web applications, integration with AOP modules, ORM and distributed applications.
It supports only Singleton and Prototype bean scopes.It supports all types of bean scopes such as Singleton, Prototype, Request, Session etc.
It does not support Annotations. In Bean Autowiring, we need to configure the properties in XML file only.It supports Annotation based configuration in Bean Autowiring.
This interface does not provides messaging (i18n or internationalization) functionality.ApplicationContext interface extends MessageSource interface, thus it provides messaging (i18n or internationalization) functionality.
BeanFactory does not support Event publication functionality.Event handling in the ApplicationContext is provided through the ApplicationEvent class and ApplicationListener interface.
In BeanFactory, we need to manually register BeanPostProcessors and BeanFactoryPostProcessors.The ApplicationContext automatically registers BeanFactoryPostProcessor and BeanPostProcessor at startup.
BeanFactory will create a bean object when the getBean() method is called thus making it Lazy initialization.ApplicationContext loads all the beans and creates objects at the time of startup only thus making it Eager initialization.
BeanFactory interface provides basic features only thus requires less memory. For standalone applications where the basic features are enough and when memory consumption is critical, we can use BeanFactory.ApplicationContext provides all the basic features and advanced features, including several that are geared towards enterprise applications thus requires more memory.

功能说明

1) Bean 自动装配

Spring 容器能够自动装配协作 bean 之间的关系。这意味着可以通过检查容器的内容让 Spring 自动为您的 bean 解析其他 bean。每个 bean 都指定了自动装配,因此可以为某些 bean 启用,而其他 bean 不会自动装配。使用自动装配,可以减少或消除指定属性或构造函数参数的需要。

BeanFactory 中的自动装配:

在 BeanFactory 中,通过使用基于 XML 的配置文件中元素的“自动装配”属性来指定 bean 定义的自动装配模式。

例子:

XML



在 ApplicationContext 中自动装配:

在 ApplicationContext 中,我们可以在 bean 类的属性或 setter 方法之上使用注解“@Autowired”

例子:

Java

@Autowired
private String name;


2) 注册 BeanPostProcessors 和 BeanFactoryPostProcessors

BeanPostProcessors:一个Bean后处理器是一个Java类,实现了org.springframework.beans.factory.config.BeanPostProcessor接口,由两个回调方法组成。它允许自定义修改由 spring 容器创建的新 bean 实例。如果我们想在 Spring 容器完成实例化、配置和初始化 bean 之前或之后实现一些自定义逻辑,我们可以插入一个或多个 BeanPostProcessor 实现。

BeanFactoryPostProcessors: Bean 工厂后处理器是一个Java类,它实现了 org.springframework.beans.factory.config.BeanFactoryPostProcessor 接口。它在实际创建 bean 之前处理 bean 的定义或配置元数据。调用它们来解决运行时依赖关系。

在 BeanFactory 中注册:

在使用 BeanFactory 接口时,如果有任何 bean 实现了 BeanPostProcessor 或 BeanFactoryPostProcessor 接口,则必须手动显式注册 bean 后处理器。

例子:

Java

// create BeanFactory
ConfigurableBeanFactory factory = new ConfigurableBeanFactory(resource);
 
// register needed BeanPostProcessors
HelloBeanPostProcessor bpp = new HelloBeanPostProcessor();
factory.addBeanPostProcessor(bpp);


在 ApplicationContext 中注册:

ApplicationContext 接口将自动检测部署到其中的任何 bean 实现 BeanPostProcessor 或 BeanFactoryPostProcessor 接口并将它们注册为后处理器,然后在 bean 创建时由工厂适当地调用它们。因此,在 ApplicationContexts 中使用 bean factory 后处理器要比在普通 BeanFactories 中方便得多。

3)加载/初始化bean

我们将通过一个简单的示例来了解 BeanFactory 和 ApplicationContext 容器之间的区别。

BeanFactory 示例:

创建以下类和 XML 文件。

欢迎豆。 Java:一个Java bean 类,用于定义属性、属性的 getter/setter 方法。

Java

public class WelcomeBean {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String welcomeMsg() {
        return "Welcome " + name;
    }
 
    public void initializeBean() {
        System.out.println("Welcome Bean is initialized!!");
    }
 
    public void destroyBean() {
        System.out.println("Welcome Bean is destroyed!!");
    }
 
}


beans.xml:用于配置 bean 的 XML 文件。

XML


 

 
    
        
    
 


欢迎豆测试。 Java:创建 BeanFactory 对象并运行应用程序的主类。

Java

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
 
import com.geeks.beans.WelcomeBean;
 
public class WelcomeBeanTest {
    public static void main(String[] args) {
 
        ClassPathResource res = new ClassPathResource("beans.xml");
        XmlBeanFactory factory = new XmlBeanFactory(res);
        System.out.println("Before getBean() method");
 
        WelcomeBean welcome = (WelcomeBean) factory.getBean("welcomeBean");
        System.out.println(welcome.welcomeMsg());
        ((XmlBeanFactory)factory).destroySingletons();
 
    }
 
}


执行:

  • 在本例中,我们调用welcomeMsg()方法在控制台中打印消息。
  • 在 bean 类中,我们指定了方法, initializeBean() 为 init-methoddestroyBean() 为 destroy-method。此配置在beans.xml文件中指定。
  • 当我们运行应用程序时,main 方法将被执行。在那,首先,它将创建资源对象以加载 XML 文件,然后创建 XmlBeanFactory 对象。
  • 然后应用程序打印,在控制台中的 getBean() 方法之前。现在,调用 getBean() 方法,此时容器将加载 bean 并初始化 bean 类。在 getBean() 方法执行之前,BeanFactory 容器不会初始化 bean。因此,它被称为延迟初始化。
  • 因此,输出将如下所示,
输出

输出

应用上下文示例:

现在,我们将使用 ApplicationContext 创建相同的应用程序。

你好豆。 Java:一个Java bean 类,用于定义属性、属性的 getter/setter 方法。

Java

public class HelloBean {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String helloMsg() {
        return "Hello " + name;
    }
 
    public void initializeBean() {
        System.out.println("Hello Bean is initialized!!");
    }
 
    public void destroyBean() {
        System.out.println("Hello Bean is destroyed!!");
    }
 
}


applicationContext.xml:用于配置 bean 的 XML 文件。

Java

public class WelcomeBean {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String welcomeMsg() {
        return "Welcome " + name;
    }
 
    public void initializeBean() {
        System.out.println("Welcome Bean is initialized!!");
    }
 
    public void destroyBean() {
        System.out.println("Welcome Bean is destroyed!!");
    }
 
}


你好豆测试。 Java : 创建 ApplicationContext 对象并运行应用程序的主类。

Java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.geeks.beans.HelloBean;
 
public class HelloBeanTest {
 
    public static void main(String[] args) {
 
        ApplicationContext con = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("Before getBean() method");
        HelloBean hello = (HelloBean) con.getBean("helloBean");
 
        System.out.println(hello.helloMsg());
        ((ClassPathXmlApplicationContext) con).close();
 
    }
 
}


执行:

  • 在此示例中,我们调用helloMsg()方法在控制台中打印消息。
  • 在 bean 类中,我们指定了方法, initializeBean()为 init-method, destroyBean()为 destroy-method。此配置在applicationContext.xml文件中指定。
  • 当我们运行应用程序时,main 方法将被执行。在那里,首先,它将 ApplicationContext 对象,现在容器本身将识别所有 bean 对象,并且它将在调用 getBean() 方法之前进行初始化。因此,它被称为渴望初始化
  • 它在调用 getBean() 方法之前首先打印初始化消息。
  • 因此,输出将如下所示,
输出

输出

如果你比较两个输出,我们可以看到使用 BeanFactory,bean 将在调用 getBean() 方法时被初始化,这意味着按需。但是 ApplicationContext 只会在启动时初始化所有的 bean。

4) ApplicationContext 中的国际化功能

ApplicationContext 接口扩展了名为MessageSourceNestingMessageSource的接口,因此提供了消息传递 (i18n) 或国际化功能。它能够解析分层消息。

例子:

Java

String getMessage (String code, Object[] args, String default, Locale loc)


这是用于从 MessageSource 检索消息的基本方法。如果未找到指定语言环境的消息,则使用默认消息。当 ApplicationContext 被加载时,它会自动搜索在上下文中定义的 MessageSource bean。 bean 的名称应该是messageSource 。目前,Spring 提供了两种 MessageSource 实现。它们是ResourceBundleMessageSourceStaticMessageSource

5)ApplicationContext中的事件传播

ApplicationContext 通过ApplicationEvent类和ApplicationListener接口提供事件处理。如果一个 bean 实现了 ApplicationListener 接口并部署到上下文中,那么每次将 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 bean。这是标准的观察者设计模式。

Spring 提供了三个标准事件,即 ContextRefreshedEvent、ContextClosedEvent 和 RequestHandledEvent。我们还可以通过调用 ApplicationContext 上的publishEvent()方法并指定一个参数来创建自定义事件,该参数是我们实现 ApplicationEvent 的自定义事件类的实例。

结论

正如我们上面所讨论的,ApplicationContext 和 BeanFactory 容器都用于创建和管理 bean 对象。 BeanFactory 是提供创建和管理 bean 对象的所有基本功能的基本接口,ApplicationContext 接口扩展了 BeanFactory 接口,它提供了所有基本功能以及一些高级功能,例如以通用方式加载文件资源的能力,向注册的侦听器发布事件、解析消息、支持国际化等。