?????這段時間開始了對spring的復(fù)習(xí),spring的模塊很多,這里主要對spring ioc容器、aop的實現(xiàn)原理和spring聲明式事務(wù)原理做下探究和總結(jié),給自己后續(xù)復(fù)習(xí)所用。
?????這里以AnnotationConfigApplicationContext作為例子,來探究下spring ioc容器的初始化過程,以及對應(yīng)的BeanDefinition的定位、載入和注冊的過程。
public static void main(String[] args) {
//編程式啟動spring容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
User user = applicationContext.getBean(User.class);
System.out.println(user);
user.testMethod();
}
?????這里以編程式啟動和使用spring容器。以AnnotationConfigApplicationContext的實例化開始啟動,實例化BeanDefinitionReader和BeandifinitionScanner。
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
//初始化ioc容器
refresh();
}
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
?????這里看看AnnotatedBeanDefinitionReader,這里面通過AnnotationConfigUtils.registerAnnotationConfigProcessors方法,給容器添加了很多BeanPostProcessor后置處理器,在Bean生命周期的初始化前后進行調(diào)用。類似關(guān)于@Autowired注解功能實現(xiàn)的AutowiredAnnotationProcessor后置處理器,在這里會添加上通用的bean后置處理器到BeanFactory容器中。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//容器初始化準備,一些標記的設(shè)立
prepareRefresh();
//獲取容器,在這里開啟了BeanDefinition的定位、載入和初始化
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//配置Classloader和ApplicationContextAwareProcessor
prepareBeanFactory(beanFactory);
try {
//擴展口子,為容器子類提供添加BeanPostProcessor
postProcessBeanFactory(beanFactory);
//調(diào)用BeanFactoryPostProcessor的postProcessBeanDefinitionRegistry方法,修改BeanDedifinition的配置元信息
invokeBeanFactoryPostProcessors(beanFactory);
//注冊自定義的BeanPostProcessor
registerBeanPostProcessors(beanFactory);
//初始化信息源,國際化用到
initMessageSource();
//初始化上下文的廣播事件
initApplicationEventMulticaster();
//擴展口子,供容器子類初始化的調(diào)用
onRefresh();
//注冊事件監(jiān)聽器
registerListeners();
//預(yù)實例化所有的單例bean
finishBeanFactoryInitialization(beanFactory);
//發(fā)布容器初始化事件
finishRefresh();
}
catch (BeansException ex) {
// ...
}
finally {
// ..
}
}
}
?????這里大致羅列下BeanFactory在refresh的時候做的事情:
- prepareRefresh容器初始化準備,設(shè)立一些標記
- obtainFreshBeanFactory獲取容器,這里開啟了BeanDefinition的定位、載入和初始化。
- prepareBeanFactory配置Classloader和ApplicationContextAwareProcessor,這里的BeanPostProcessor可以在每個Bean實例化之前設(shè)置beanName和ApplicationContext等其它容器相關(guān)引用。
-invokeBeanFactoryPostProcessors調(diào)用BeanFactoryPostProcessor的postProcessBeanDefinitionRegistry方法,可以用來修改任何Bean的定義信息,修改Bean定義的。 - registerBeanPostProcessors注冊自定義的一些后置處理器,可以用來在每個bean初始化前后進行處理。
- finishBeanFactoryInitialization這里是在容器初始化的時候,對一些需要預(yù)實例化的單例Bean進行提前實例化加載。
?????下面來看初始化容器的核心方法obtainFreshBeanFactory,BeanDefinition的定位、加載和注冊。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//初始化容器
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//返回容器
return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException {
//如果容器已經(jīng)初始化,銷毀容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//這里去創(chuàng)建了一個DefaultListableBeanFactory作為spring ioc容器的具體容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//這里去加載bean的定義信息BeanDefinition
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
} catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
?????這里創(chuàng)建了一個DefaultListableBeanFactory作為spring ioc的具體容器實現(xiàn),然后在loadBeanDefinitions里面去加載bean的定義信息。AbstractXmlApplicationContext用來解析加載xml定義的bean信息,AnnotationConfigWebApplicationContext用來解析加載注解配置的bean信息。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
?????可以看到對應(yīng)xml配置的bean定義信息,是用XmlBeanDefinitionReader來加載解析bean的定義信息。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// ...
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//獲取xml文件流
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
// ...
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
?????在這里獲取xml配置的bean定義信息的文件路徑,然后把文件轉(zhuǎn)化成InputStream文件流,依靠文件流獲取配置信息。然后把文件流里面的信息讀出來,形成一個Document對象,然后依靠BeanDefinitionDocumentReader來解析bean的定義信息,然后再把bean定義信息注冊到容器中。最后的結(jié)果是在beanDefinitionMap中存儲了bean的配置信息。
最后以一張時序圖作為spring容器初始化BeanDefinition加載的總結(jié):
