IOC源码解析
IOC初始化
对于spring我们最熟悉的莫过于ApplicationContext这一接口了,首先回顾一下spring的使用流程
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
上述代码获得了一个ApplicationContext容器,但是spring中的bean是如何注入到容器中去的呢?
这里从构造函数开始入手
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
//解析Bean定义资源文件的路径,处理多个资源文件字符串数组
setConfigLocations(configLocations);
if (refresh) {
//入口方法
refresh();
}
}
从构造函数可以看出IOC的入口就是refresh方法,该方法在AbstractApplicationContext中
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
//子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//3、为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//4、为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//5、调用所有注册的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//6、为BeanFactory注册BeanPost事件处理器.
//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//7、初始化信息源,和国际化相关.
initMessageSource();
// Initialize event multicaster for this context.
//8、初始化容器事件传播器.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//9、调用子类的某些特殊Bean初始化方法
onRefresh();
// Check for listener beans and register them.
//10、为事件传播器注册事件监听器.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//11、初始化所有剩余的单例Bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
//13、销毁已创建的Bean
destroyBeans();
// Reset 'active' flag.
//14、取消refresh操作,重置容器的同步标识。
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
//15、重设公共缓存
resetCommonCaches();
}
}
}
这里可以看出obtainFreshBeanFactory方法获得了一个BeanFactory容器
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
这里调用了refreshBeanFactory方法这是一个抽象方法,具体逻辑由子类实现
这里进入AbstractRefreshableApplicationContext中的refreshBeanFactory方法
protected final void refreshBeanFactory() throws BeansException {
//如果已经有容器,销毁容器中的bean,关闭容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建IOC容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等(这里解析了是否允许循环引用)
customizeBeanFactory(beanFactory);
//调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
这里调用loadBeanDefinitions方法解析BeanDefinition,他是一个抽象方法同时是由子类实现
其中AbstractRefreshableApplicationContext主要有四个实现
AbstractXmlApplicationContext 解析xml
AnnotationConfigWebApplicationContext 解析注解
GroovyWebApplicationContext 适配groovy
XmlWebApplicationContext web环境
这里进入AbstractXmlApplicationContext的loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
//创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
//为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的
//祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
//为Bean读取器设置SAX xml解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
//当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
initBeanDefinitionReader(beanDefinitionReader);
//Bean读取器真正实现加载的方法
loadBeanDefinitions(beanDefinitionReader);
}
这里使用beanDefinitionReader类解析,最终使用loadBeanDefinitions方法去加载
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//获取Bean定义资源的定位
Resource[] configResources = getConfigResources();
if (configResources != null) {
//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
//的Bean定义资源
reader.loadBeanDefinitions(configResources);
}
//如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
String[] configLocations = getConfigLocations();
if (configLocations != null) {
//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
//的Bean定义资源
reader.loadBeanDefinitions(configLocations);
}
}
追踪loadBeanDefinitions方法最终执行到XmlBeanDefinitionReader中的doLoadBeanDefinitions方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//将XML文件转换为DOM对象,解析过程由documentLoader实现
Document doc = doLoadDocument(inputSource, resource);
//这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
最终调用DefaultBeanDefinitionDocumentReader中的doRegisterBeanDefinitions方法
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
//具体的解析过程由BeanDefinitionParserDelegate实现,
//BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
preProcessXml(root);
//从Document的根元素开始进行Bean定义的Document对象
parseBeanDefinitions(root, this.delegate);
//在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
postProcessXml(root);
this.delegate = parent;
}
preProcessXml,postProcessXml是两个扩展方法,由用户自己实现,用来对Bean解析的前后加入自定义解析逻辑
parseBeanDefinitions方法开始从根元素解析Bean
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//Bean定义的Document对象使用了Spring默认的XML命名空间
if (delegate.isDefaultNamespace(root)) {
//获取Bean定义的Document对象根元素的所有子节点
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//获得Document节点是XML元素节点
if (node instanceof Element) {
Element ele = (Element) node;
//Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
if (delegate.isDefaultNamespace(ele)) {
//使用Spring的Bean规则解析元素节点
parseDefaultElement(ele, delegate);
}
else {
//没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点
delegate.parseCustomElement(ele);
}
}
}
}
else {
//Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的
//解析规则解析Document根节点
delegate.parseCustomElement(root);
}
}
parseDefaultElement方法
////使用Spring的Bean规则解析Document元素节点
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//如果元素节点是<Import>导入元素,进行导入解析
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//如果元素节点是<Alias>别名元素,进行别名解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,
//按照Spring的Bean规则解析元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
parseCustomElement方法
//用户自定义解析规则
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
importBeanDefinitionResource,processAliasRegistration自行观看,这里列出processBeanDefinition方法
//解析Bean定义资源Document对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
// BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
//对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
// BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
//在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
在BeanDefinitionParserDelegate类下parseBeanDefinitionElement解析成BeanDefinitionHolder
//解析Bean定义资源文件中的<Bean>元素,这个方法中主要处理<Bean>元素的id,name和别名属性
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取<Bean>元素中的id属性值
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取<Bean>元素中的name属性值
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//获取<Bean>元素中的alias属性值
List<String> aliases = new ArrayList<>();
//将<Bean>元素中的所有name属性值存放到别名中
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
//如果<Bean>元素中没有配置id属性时,将别名中的第一个值赋值给beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//检查<Bean>元素所配置的id或者name的唯一性,containingBean标识<Bean>
//元素中是否包含子<Bean>元素
if (containingBean == null) {
//检查<Bean>元素所配置的id、name或者别名是否重复
checkNameUniqueness(beanName, aliases, ele);
}
//详细对<Bean>元素中配置的Bean定义进行解析的地方
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
//如果<Bean>元素中没有配置id、别名或者name,且没有包含子元素
//<Bean>元素,为解析的Bean生成一个唯一beanName并注册
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
//如果<Bean>元素中没有配置id、别名或者name,且包含了子元素
//<Bean>元素,为解析的Bean使用别名向IOC容器注册
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
//为解析的Bean使用别名注册时,为了向后兼容
//Spring1.2/2.0,给别名添加类名后缀
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
//当解析出错时,返回null
return null;
}
解析完成之后调用BeanDefinitionReaderUtils中的registerBeanDefinition方法进行注册
最终调用DefaultListableBeanFactory中的registerBeanDefinition方法,将BeanDefinition信息放到beanDefinitionMap
容器中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
registerBeanDefinition方法
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//...
//校验解析的BeanDefiniton
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
//从容器中拿到BeanDefinition
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
//如果容器中已经有该BeanDefinition信息
//1 !isAllowBeanDefinitionOverriding 不允许覆盖
//2 int ROLE_APPLICATION = 0;
// int ROLE_SUPPORT = 1;
// int ROLE_INFRASTRUCTURE = 2;
//3
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
//log信息省略...
//将原来的覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//原本容器中没有BeanDefinition信息
else {
//有其他BeanDefinition正在放到容器,等待其他执行完毕,ArrayList不是线程安全的
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
//注册的过程中需要线程同步,以保证数据的一致性
synchronized (this.beanDefinitionMap) {
//当前BeanDefinition放到容器
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//检查是否有同名的BeanDefinition已经在IOC容器中注册
if (oldBeanDefinition != null || containsSingleton(beanName)) {
//重置所有已经注册过的BeanDefinition的缓存
resetBeanDefinition(beanName);
}
}
至此IOC流程执行完毕,下面总结画出调用时序图
以上主要分为三个流程 定位
加载
注册
IOC源码解析完毕,下次通过源码分析,解析DI的过程
网友评论