Spring – BeanFactory 和 ApplicationContext 的区别
Spring 是最流行的Java EE 框架之一。它是一个开源轻量级框架,允许Java EE 开发人员构建简单、可靠和可扩展的企业应用程序。它提供了面向方面的编程。它为所有通用和中间件服务提供支持,主要侧重于提供各种方式来帮助您管理业务对象。它是一个模块化框架,其中所有模块都是根据称为“依赖注入”的概念设计的。
依赖注入:依赖注入是一种设计模式,它允许spring容器将对象“注入”到其他对象或依赖项中。简单来说,创建对象和管理 Spring 组件的控制由 Spring 容器负责。
弹簧容器
Spring Framework 提供了两个最基本和最重要的包,它们是org.springframework.beans和org.springframework.context包。这些包中的代码为 Spring 的控制反转/依赖注入特性提供了基础。 Spring 容器负责创建 bean 对象并将它们注入到类中。这两个容器是,
- BeanFactory(I) – 在 org.springframework.beans.factory 包中可用。
- ApplicationContext(I) – 在 rg.springframework.context 包中可用。
BeanFactory 接口
这是访问 Spring bean 容器的根接口。它是实例化、配置和管理大量 bean 的实际容器。这些 bean 相互协作,因此它们之间存在依赖关系。这些依赖关系反映在 BeanFactory 使用的配置数据中。该接口由包含许多 bean 定义的对象实现,每个定义由一个字符串名称唯一标识。这个 BeanFactory 最常用的实现类是org.springframework.beans.factory.xml 包中的XmlBeanFactory 。
Note: BeanFactory is deprecated from Spring 3.0.
示例代码:
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、加载多个(分层)上下文等。有很多实现类可以使用诸如ClassPathXmlApplicationContext 、 FileSystemXmlApplicationContext 、 AnnotationConfigWebApplicationContext等。
示例代码:
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 的配置文件中
例子:
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-method , destroyBean() 为 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 接口扩展了名为MessageSource和NestingMessageSource的接口,因此提供了消息传递 (i18n) 或国际化功能。它能够解析分层消息。
例子:
Java
String getMessage (String code, Object[] args, String default, Locale loc)
这是用于从 MessageSource 检索消息的基本方法。如果未找到指定语言环境的消息,则使用默认消息。当 ApplicationContext 被加载时,它会自动搜索在上下文中定义的 MessageSource bean。 bean 的名称应该是messageSource 。目前,Spring 提供了两种 MessageSource 实现。它们是ResourceBundleMessageSource和StaticMessageSource 。
5)ApplicationContext中的事件传播
ApplicationContext 通过ApplicationEvent类和ApplicationListener接口提供事件处理。如果一个 bean 实现了 ApplicationListener 接口并部署到上下文中,那么每次将 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 bean。这是标准的观察者设计模式。
Spring 提供了三个标准事件,即 ContextRefreshedEvent、ContextClosedEvent 和 RequestHandledEvent。我们还可以通过调用 ApplicationContext 上的publishEvent()方法并指定一个参数来创建自定义事件,该参数是我们实现 ApplicationEvent 的自定义事件类的实例。
结论
正如我们上面所讨论的,ApplicationContext 和 BeanFactory 容器都用于创建和管理 bean 对象。 BeanFactory 是提供创建和管理 bean 对象的所有基本功能的基本接口,ApplicationContext 接口扩展了 BeanFactory 接口,它提供了所有基本功能以及一些高级功能,例如以通用方式加载文件资源的能力,向注册的侦听器发布事件、解析消息、支持国际化等。