这段时间开始了对spring的复习,spring的模块很多,这里主要对spring ioc容器、aop的实现原理和spring声明式事务原理做下探究和总结,给自己后续复习所用。
这里以AnnotationConfigApplicationContext作为例子,来探究下spring ioc容器的初始化过程,以及对应的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生命周期的初始化前后进行调用。类似关于@Autowired注解功能实现的AutowiredAnnotationProcessor后置处理器,在这里会添加上通用的bean后置处理器到BeanFactory容器中。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//容器初始化准备,一些标记的设立
prepareRefresh();
//获取容器,在这里开启了BeanDefinition的定位、载入和初始化
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//配置Classloader和ApplicationContextAwareProcessor
prepareBeanFactory(beanFactory);
try {
//扩展口子,为容器子类提供添加BeanPostProcessor
postProcessBeanFactory(beanFactory);
//调用BeanFactoryPostProcessor的postProcessBeanDefinitionRegistry方法,修改BeanDedifinition的配置元信息
invokeBeanFactoryPostProcessors(beanFactory);
//注册自定义的BeanPostProcessor
registerBeanPostProcessors(beanFactory);
//初始化信息源,国际化用到
initMessageSource();
//初始化上下文的广播事件
initApplicationEventMulticaster();
//扩展口子,供容器子类初始化的调用
onRefresh();
//注册事件监听器
registerListeners();
//预实例化所有的单例bean
finishBeanFactoryInitialization(beanFactory);
//发布容器初始化事件
finishRefresh();
}
catch (BeansException ex) {
// ...
}
finally {
// ..
}
}
}
这里大致罗列下BeanFactory在refresh的时候做的事情:
- prepareRefresh容器初始化准备,设立一些标记
- obtainFreshBeanFactory获取容器,这里开启了BeanDefinition的定位、载入和初始化。
- prepareBeanFactory配置Classloader和ApplicationContextAwareProcessor,这里的BeanPostProcessor可以在每个Bean实例化之前设置beanName和ApplicationContext等其它容器相关引用。
-invokeBeanFactoryPostProcessors调用BeanFactoryPostProcessor的postProcessBeanDefinitionRegistry方法,可以用来修改任何Bean的定义信息,修改Bean定义的。 - registerBeanPostProcessors注册自定义的一些后置处理器,可以用来在每个bean初始化前后进行处理。
- finishBeanFactoryInitialization这里是在容器初始化的时候,对一些需要预实例化的单例Bean进行提前实例化加载。
下面来看初始化容器的核心方法obtainFreshBeanFactory,BeanDefinition的定位、加载和注册。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//初始化容器
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//返回容器
return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException {
//如果容器已经初始化,销毁容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//这里去创建了一个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());
}
这里创建了一个DefaultListableBeanFactory作为spring ioc的具体容器实现,然后在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);
}
可以看到对应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定义信息的文件路径,然后把文件转化成InputStream文件流,依靠文件流获取配置信息。然后把文件流里面的信息读出来,形成一个Document对象,然后依靠BeanDefinitionDocumentReader来解析bean的定义信息,然后再把bean定义信息注册到容器中。最后的结果是在beanDefinitionMap中存储了bean的配置信息。
最后以一张时序图作为spring容器初始化BeanDefinition加载的总结: