这次我们从源码角度来聊聊BeanFactory
和ApplicationContext
的关系,讲一些网上文章不曾提到的点。
官方描述
先来看一下官方文档中关于BeanFactory
和ApplicationContext
的描述。
从官方文档可以了解到:
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
才是同一个实例对象。