BeanFactory 是 Spring IoC 容器的底层实现;
ApplicationContext 拥有 BeanFactory 的所有能力,还提供了
- 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-framework/docs/5.2.2.RELEASE
即更易集成 aop 特性、消息资源处理(国际化)、事件发布、应用程序层面特定的上下文如 WebApplicationContext。
除了以上,细节上还包括:
- BeanFactory 在启动的时候不会去实例化 bean,从容器中拿 bean 时才会去实例化;ApplicationContext 在启动时就把所有的 bean 全部实例化了
- BeanPostProcessor、BeanFactoryPostProcessor 接口的注册:BeanFactory 需要手动注册,ApplicationContext 则是自动
总之,ApplicationContext 是具备应用特性的 BeanFactory 超集。
代码示例:
pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>constxiong</groupId>
<artifactId>spring-study</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>003-spring-beanfactory-applicationcontext</artifactId>
<properties>
<spring-version>5.2.2.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
</dependencies>
<build>
</build>
</project>
User.java
package constxiong;
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
spring 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="constxiong.User">
<property name="id" value="1"/>
<property name="name" value="constxiong"/>
</bean>
</beans>
测试代码
package constxiong;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 测试 BeanFactory 与 ApplicationContext 的区别
* @author ConstXiong
*/
public class Test {
public static void main(String[] args) {
String xmlPath = "META-INF/spring-beanfactory-applicationcontext.xml";
getBeanByBeanFactory(xmlPath);
getBeanByApplicationContext(xmlPath);
}
/**
* 通过 ClassPathXmlApplicationContext 获取 bean
*/
private static void getBeanByApplicationContext(String xmlPath) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
User user = applicationContext.getBean(User.class);
System.out.println(user);
}
/**
* 通过 DefaultListableBeanFactory 获取 bean
*/
private static void getBeanByBeanFactory(String xmlPath) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(beanFactory);
xmlReader.loadBeanDefinitions(xmlPath);
User user = beanFactory.getBean(User.class);
System.out.println(user);
}
}
说明:
- 通过在 BeanFactory#getBean,ApplicationContext#getBean 方法这两行、User#setId 方法打上断点,可以看出 BeanFactory 是在调用 getBean 时初始化 User 这个 bean,ApplicationContext 是提前初始化完成的。
- 通过查看源码可以看出,AbstractRefreshableApplicationContext 类间接继承了 BeanFactory 接口,同时持有 DefaultListableBeanFactory 对象 beanFactory;所有 BeanFactory 的能力都来自于 beanFactory。这点用到了装饰器设计模式。
- ApplicationContext 对 BeanFactory 的能力的扩展体现在 AbstractApplicationContext#refresh 方法内。
【Java学习资源】整理推荐
- Spring 依赖注入的处理过程与 DependencyDescriptor 的说明
- Spring 各种 Aware 接口回调注入
- Spring Bean 生命周期内的 Exception 复现
- Spring 内建 Bean
- Spring Bean 的别名
- Spring Bean 未指定名称的命名规则
- Bean 何时被 GC
- Spring Bean 延迟加载
- ObjectFactory 与 BeanFactory 的区别
- Bean 销毁的方式与顺序
- Bean 初始化的方式与顺序
- Bean 的实例化方式
- Bean的注册方式
- 什么是 BeanDefinition?
- Spring IoC 容器启动时做了什么?
- BeanFactory 与 FactoryBean 的区别
- BeanFactory 与 ApplicationContext 的区别
- Spring IoC 依赖注入的实现方式
- Spring IoC 依赖注入(支持哪些数据类型?)
- Spring bean 依赖查找
- Spring-IoC
- Spring 的核心特性