1.本章说明
本章主要讨论 BeanFactory
和 ApplicationContext
谁才是 Spring IoC 容器?
2.验证
- 上一篇:夯实Spring系列|第三章:IoC 依赖注入
- github 地址:https://github.com/huajiexiewenfeng/thinking-in-spring
- 接着第三章的代码继续来看 到底谁才是 Spring IoC 容器?
在上一章中,我们通过byType
类型注入的方式,将BeanFactory
的对象注入到UserRepository
中。
2.1 示例
本例中通过userRepository.getBeanFactory()
获取这个 BeanFactory 对象与 main()
方法中的 beanFactory
进行比较。
/**
* 依赖注入示例
*/
public class DependencyInjectionDemo {
public static void main(String[] args) {
//配置 xml 配置文件
//启动 spring 应用上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml ");
//自定义Bean
UserRepository userRepository = beanFactory.getBean("userRepository", UserRepository.class);
whoIsIocContainer(userRepository, beanFactory);
}
private static void whoIsIocContainer(UserRepository userRepository, BeanFactory beanFactory) {
// ConfigurableApplicationContext -> ApplicationContext -> BeanFactory
// 在上下文的实现中采用的是组合模式,org.springframework.context.support.AbstractRefreshableApplicationContext 中
// 在接口的实现上又继承了 BeanFactory
System.out.println("userRepository.getBeanFactory():" + userRepository.getBeanFactory());
System.out.println("beanFactory:" + beanFactory);
System.out.println("两者是否相等:" + (userRepository.getBeanFactory() == beanFactory));
}
}
控制台输出结果
userRepository.getBeanFactory():org.springframework.beans.factory.support.DefaultListableBeanFactory@7b227d8d: defining beans [user,superUser,objectFactory,userRepository]; root of factory hierarchy
beanFactory:org.springframework.context.support.ClassPathXmlApplicationContext@7f690630, started on Fri Apr 17 21:53:16 CST 2020
两者是否相等:false
由结果可知两者并不相同。
那么DefaultListableBeanFactory
和 ClassPathXmlApplicationContext
这两个对象是什么关系?
2.2 Spring 官网其实对两者的关系做了一定的说明
The
org.springframework.beans
andorg.springframework.context
packages are the basis for Spring Framework’s IoC container. TheBeanFactory
interface provides an advanced configuration mechanism capable of managing any type of object.ApplicationContext
is a sub-interface ofBeanFactory
. It adds:
- Easier integration with Spring’s AOP features 集成Spring AOP 特性
- Message resource handling (for use in internationalization) 国际化
- Event publication 事件发布
- Application-layer specific contexts such as the
WebApplicationContext
for use in web applications. 应用级别的上下文,比如WEB应用使用的WebApplicationContext
In short, the
BeanFactory
provides the configuration framework and basic functionality, and theApplicationContext
adds more enterprise-specific functionality. TheApplicationContext
is a complete superset of theBeanFactory
…
ApplicationContext 就是 BeanFactory,但是他们是两个不同的对象,BeanFactory 提供框架配置和基本功能,ApplicationContext 是 BeanFactory 的一个超集,一个子接口,ApplicationContext 提供更多的企业特性。
ApplicationContext 除了 IOC 容器角色,还提供
- 面向切面 (AOP)
- 配置元信息(Configuration Metadata)
- 资源配置(Resource)
- 事件(Events)
- 国际化(i18n)
- 注解(Annaotions)
- Environment 抽象(Environment Abstraction)
2.3 源码分析
ApplicationContext 的层次关系比较复杂,我们直接定位到相关的类
- org.springframework.context.support.AbstractRefreshableApplicationContext
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
@Nullable
private Boolean allowBeanDefinitionOverriding;
@Nullable
private Boolean allowCircularReferences;
/** Bean factory for this context. */
@Nullable
private DefaultListableBeanFactory beanFactory;
...
-
AbstractRefreshableApplicationContext
用组合的方式,获取到BeanFactory
的默认实现DefaultListableBeanFactory
-
再看它的父类
AbstractApplicationContext
中的getBean()
方法,其实是getBeanFactory()
获取的这个DefaultListableBeanFactory
对象,再调用beanFactory.getBean(name)
方法来获取 Bean 对象,最终还是 BeanFactory 来获取 Bean 对象。 -
由此可见,其实真正的底层 IoC 容器其实是 BeanFactory 。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
...
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, args);
}
...
3.结论
-
ApplicationContext 是 BeanFactory 的一个超集,一个子接口;BeanFactory 提供框架配置和基本功能,ApplicationContext 提供更多的企业特性。
-
BeanFactory 才是真正的底层的 IoC 容器,因为 ApplicationContext 最终还是通过组合 BeanFactory 来实现 getBean() 方法
4.参考
- 极客时间-小马哥《小马哥讲Spring核心编程思想》