从源码角度来看BeanFactory和ApplicationContext的关系
大家好,我是小黑,这是年前的最后一篇推文,提前祝大家新年快乐~~
这次我们从源码角度来聊聊BeanFactory
和ApplicationContext
的关系,讲一些网上文章不曾提到的点。
官方描述
先来看一下官方文档中关于BeanFactory
和ApplicationContext
的描述。
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
- 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/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-beanfactory
从官方文档可以了解到:
BeanFactory
接口提供了能够管理任何类型对象的高级配置机制。
ApplicationContext
是BeanFactory
的子接口,它增加了如下一些功能:
- 更容易与 Spring 的 AOP 集成
- 消息资源处理,用于国际化
- 事件发布
- 特定于应用程序层的上下文,如用于 web 应用程序的
WebApplicationContext
。
源码简析
以下源码基于 Spring 5.0.13 版本。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
public interface ListableBeanFactory extends BeanFactory
从源码可以证实到,ApplicationContext
继承了BeanFactory
。
@Configurable
public class Main {
@Autowired
BeanFactory beanFactory;
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
Main bean = context.getBean(Main.class);
// false
System.out.println(context == bean.beanFactory);
context.close();
}
}
AnnotationConfigApplicationContext
是ApplicationContext
的一个实现类,换而言之,AnnotationConfigApplicationContext
也是BeanFactory
的一个实现类。
但是,运行上述代码,System.out.println(context == bean.beanFactory);
的输出结果为false
。
这是不是意味着,在容器中,ApplicationContext
和BeanFactory
是两个不同的实例对象呢?
BeanFactory 和 ApplicationContext
在AnnotationConfigApplicationContext
中有一个getBeanFactory
方法。
准确来说,是org.springframework.context.support.AbstractApplicationContext#getBeanFactory
。
@Configurable
public class Main {
@Autowired
BeanFactory beanFactory;
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
Main bean = context.getBean(Main.class);
// false
System.out.println(context == bean.beanFactory);
// true
System.out.println(context.getBeanFactory() == bean.beanFactory);
context.close();
}
}
AbstractApplicationContext
是ApplicationContext
的抽象实现。
AnnotationConfigApplicationContext
继承了GenericApplicationContext
,而GenericApplicationContext
又继承了AbstractApplicationContext
。
在AbstractApplicationContext
中,所有BeanFactory
接口的实现,都是委托给了BeanFactory
对象。
// AbstractApplicationContext#getBean(java.lang.Class<T>, java.lang.Object...)
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(requiredType, args);
}
// AbstractApplicationContext#getBeanFactory
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
getBeanFactory()
是一个抽象方法用。
GenericApplicationContext
实现了该抽象方法:
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
...
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
...
}
总结
ApplicationContext
是BeanFactory
的子接口,但是ApplicationContext
的实例对象和BeanFactory
的实例对象并不是同一个。
在ApplicationContext
的实现中,有一个成员变量DefaultListableBeanFactory beanFactory
,所有和BeanFactory
接口相关的功能都是委派给这个成员变量来实现的。
ApplicationContext
实现类中的beanFactory
成员变量和容器中的BeanFactory
才是同一个实例对象。