spring ioc源码解析
最近详细的阅读了spring ioc的源码,记录下自己的阅读成果
几个重要概念
-BeanFactory,ApplicationContext,BeanDefinition
其中BeanFactory是最屌丝的ioc容器,而ApplicationContext可以称为高富帅,它集成了额外的功能,如国际化等。BeanFactory和AC作为容器,用CurrentHashMap存储了beanName和bean的映射关系,其中bean就是用BeanDefinition来表示的
具体步骤
ioc容器的初始化,具体可以分为BeanDefinition的定位,载入,注册。
定位:找到提供的xml地址,转化成Resource对象
载入:用BeanDefinitionReader读取Resource对象,处理beans,import, bean等标签
注册:使用BeanDefinitionRegistry把BD存到HashMap中
疑问:使用@Component,@Service那些个注解的bean是在什么时候被注入的?
以我们最经常用的FileSystemXmlApplicationContext为例:
1、
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
首先调用了父类AbstractApplicationContext的refresh方法。
2、refresh方法中主要调用obtainFreshBeanFactory方法来获取一个最新的BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
3、在obtainFreshBeanFactory中调用refreshBeanFactory重新初始化一个BF
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 重新初始化一个BeanFactory
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
4、refreshBeanFactory在父类AbstractRefreshableApplicationContext中
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
可以看到,里面初始化了一个DefaultListableBeanFactory,然后调用loadBeanDefinitions这个方法,把BeanDefinition注册到BeanFactory中
5、loadBeanDefinitions这个方法在AbstractXmlApplicationContext这个class中
@Override
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);
}
里面首先初始化了一个beanDefinitionReader,然后调用loadBeanDefinitions,接下来会调用reader的loadBeanDefinitions方法
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
6、真正的load过程是在XmlBeanDefinitionReader中来完成的,然后在这个reader中,又用BeanDefinitionDocumentReader去register每一个BeanDefinition
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;
}
7、具体的register过程会在DefaultBeanDefinitionDocumentReader完成
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
可以看到这里会有两种parse方式,default和custom,其中default针对于beans,bean,import这类标签,而custom则针对context:compont-scan这类标签。之前提到过的@Component这类注解的bean也是在parseCustomElement时被注入的。
8、最后的最后
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());这个方法,把BeanDefinition添加到HashMap中