大家好撒踪,我是小黑苇本,這是年前的最后一篇推文霞篡,提前祝大家新年快樂(lè)~~
這次我們從源碼角度來(lái)聊聊BeanFactory
和ApplicationContext
的關(guān)系,講一些網(wǎng)上文章不曾提到的點(diǎn)糙臼。
官方描述
先來(lái)看一下官方文檔中關(guān)于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.
從官方文檔可以了解到:
BeanFactory
接口提供了能夠管理任何類型對(duì)象的高級(jí)配置機(jī)制冈爹。
ApplicationContext
是BeanFactory
的子接口属愤,它增加了如下一些功能:
- 更容易與 Spring 的 AOP 集成
- 消息資源處理,用于國(guó)際化
- 事件發(fā)布
- 特定于應(yīng)用程序?qū)拥纳舷挛淖崖缬糜?web 應(yīng)用程序的
WebApplicationContext
浸遗。
源碼簡(jiǎn)析
以下源碼基于 Spring 5.0.13 版本。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
public interface ListableBeanFactory extends BeanFactory
從源碼可以證實(shí)到箱亿,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
的一個(gè)實(shí)現(xiàn)類,換而言之,AnnotationConfigApplicationContext
也是BeanFactory
的一個(gè)實(shí)現(xiàn)類髓帽。
但是菠赚,運(yùn)行上述代碼,System.out.println(context == bean.beanFactory);
的輸出結(jié)果為false
郑藏。
這是不是意味著衡查,在容器中,ApplicationContext
和BeanFactory
是兩個(gè)不同的實(shí)例對(duì)象呢必盖?
BeanFactory 和 ApplicationContext
在AnnotationConfigApplicationContext
中有一個(gè)getBeanFactory
方法拌牲。
準(zhǔn)確來(lái)說(shuō),是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
的抽象實(shí)現(xiàn)塌忽。
AnnotationConfigApplicationContext
繼承了GenericApplicationContext
,而GenericApplicationContext
又繼承了AbstractApplicationContext
失驶。
在AbstractApplicationContext
中土居,所有BeanFactory
接口的實(shí)現(xiàn),都是委托給了BeanFactory
對(duì)象嬉探。
// 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()
是一個(gè)抽象方法用擦耀。
GenericApplicationContext
實(shí)現(xiàn)了該抽象方法:
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
...
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
...
}
總結(jié)
ApplicationContext
是BeanFactory
的子接口,但是ApplicationContext
的實(shí)例對(duì)象和BeanFactory
的實(shí)例對(duì)象并不是同一個(gè)涩堤。
在ApplicationContext
的實(shí)現(xiàn)中眷蜓,有一個(gè)成員變量DefaultListableBeanFactory beanFactory
,所有和BeanFactory
接口相關(guān)的功能都是委派給這個(gè)成員變量來(lái)實(shí)現(xiàn)的定躏。
ApplicationContext
實(shí)現(xiàn)類中的beanFactory
成員變量和容器中的BeanFactory
才是同一個(gè)實(shí)例對(duì)象账磺。