你們好,我是小黑,這是年前的最後一篇推文,提早祝你們新年快樂~~html
此次咱們從源碼角度來聊聊BeanFactory
和ApplicationContext
的關係,講一些網上文章未曾提到的點。java
先來看一下官方文檔中關於BeanFactory
和ApplicationContext
的描述。web
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:spring
Easier integration with Spring’s AOP featuresapp
Message resource handling (for use in internationalization)ide
Event publicationui
Application-layer specific contexts such as the
WebApplicationContext
for use in web applications.this
從官方文檔能夠了解到:code
BeanFactory
接口提供了可以管理任何類型對象的高級配置機制。
ApplicationContext
是BeanFactory
的子接口,它增長了以下一些功能:
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
是兩個不一樣的實例對象呢?
在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
纔是同一個實例對象。