spring(四):IoC初始化流程&BeanDefinition加载注册
ApplicationContext context = new ClassPathXmlApplicationContext("hello.xml");
/**
*
* @param configLocations Spring的xml配置文件
* @param refresh 是否需要刷新,决定了是否进行bean解析、注册及实例化
* @param parent 父ApplicationContext
* @throws BeansException
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);
// 设置框架要加载的资源文件的位置<<AbstractRefreshableConfigApplicationContext>>
this.setConfigLocations(configLocations);
if (refresh) {
// ★
this.refresh(); // <AbstractApplicationContext>
}
}
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
// 容器预先准备,记录容器启动时间和标记
this.prepareRefresh();
// 创建bean工厂,里面实现了BeanDefinition的装载★
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 配置bean工厂的上下文信息,如类装载器等
this.prepareBeanFactory(beanFactory);
try {
// 在BeanDefinition被装载后,提供一个修改BeanFactory的入口
postProcessBeanFactory(beanFactory);
this.postProcessBeanFactory(beanFactory);
// 在bean初始化之前,提供对BeanDefinition修改入口
// PropertyPlaceholderConfigurer在这里被调用
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessors,用于在bean被初始化时进行拦截,进行额外初始化操作
this.registerBeanPostProcessors(beanFactory);
// 初始化MessageSource
this.initMessageSource();
// 初始化上下文事件广播
this.initApplicationEventMulticaster();
// 这是一个模板方法
this.onRefresh();
// 注册监听器
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
...
} finally {
this.resetCommonCaches();
}
}
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 如果存在BeanFactory则销毁并关闭
// 然后新建一个DefaultListableBeanFactory
// 然后进行BeanFactory的属性设置,设置是否允许重写BeanDefinition、是否允许循环引用
// 接着载入BeanDefinition<根据用途不同有多个实现子类>
this.refreshBeanFactory(); // <<AbstractRefreshableApplicationContext>>
return this.getBeanFactory();
}
// 例:具体实现子类AbstractXmlApplicationContext
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
// ★
this.loadBeanDefinitions(beanDefinitionReader);
}
// AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 取得ResourceLoader,这里是DefaultResourceLoader
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader == null) {
...
} else {
int count;
// 路径模式解析,得到指向Bean定义信息的资源集合
if (resourceLoader instanceof ResourcePatternResolver) {
try {
// DefaultResourceLoader的getResources完成具体定位
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
count = this.loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
...
return count;
}...
} else {
// DefaultResourceLoader的getResources完成具体定位★
...
}
}
}
---开始获取资源---
// DefaultResourceLoader
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
Iterator var2 = this.protocolResolvers.iterator();
Resource resource;
do {
if (!var2.hasNext()) {
if (location.startsWith("/")) {
return this.getResourceByPath(location);
}
if (location.startsWith("classpath:")) {
return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
}
try {
URL url = new URL(location);
return (Resource)(ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
} catch (MalformedURLException var5) {
return this.getResourceByPath(location);
}
}
ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();
resource = protocolResolver.resolve(location, this);
} while(resource == null);
return resource;
}
---资源获取完毕---
// XmlBeanDefinitionReader
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
// 将xml配置文件转成Document,这里使用了SAX对XML的解析
Document doc = this.doLoadDocument(inputSource, resource);
// ★
int count = this.registerBeanDefinitions(doc, resource);
}
...
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader(); // 通过反射获取
int countBefore = this.getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource)); // <<BeanDefinitionDocumentReader>>接口方法
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
// 具体实现:DefaultBeanDefinitionDocumentReader
protected void doRegisterBeanDefinitions(Element root) {
// BeanDefinition的具体解析是由BeanDefinitionParserDelegate完成的
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
...
this.preProcessXml(root);
// ★
this.parseBeanDefinitions(root, this.delegate);
this.postProcessXml(root);
this.delegate = parent;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
// 对Document中元素、节点的不断解析。
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)) {
// 一个是默认标签的解析,如Spring自己定义的标签★
this.parseDefaultElement(ele, delegate);
} else {
// 一个是对自定义标签的解析,如自定义的标签
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, "bean")) {
// <DefaultListableBeanFactory> this.beanDefinitionMap.put(...);
this.processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, "beans")) {
// 递归
this.doRegisterBeanDefinitions(ele);
}
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 这里是重点!!!BeanDefinition的具体解析是由BeanDefinitionParserDelegate完成的!!!★
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// <<BeanDefinitionRegistry>> registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
// 这里的BeanDefinition就是通过bdHolder获取的(definitionHolder.getBeanDefinition())
// 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
---开始解析,载入---
// BeanDefinitionParserDelegate
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
// 取得<bean>中id、name、aliases等属性值
String id = ele.getAttribute("id");
String nameAttr = ele.getAttribute("name");
List<String> aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
...
// 详细解析,比如构造函数、属性等
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
...
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}...
}
---结束载入---
---开始注册---
// DefaultListableBeanFactory
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
...
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
...抛出异常
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
this.removeManualSingletonName(beanName);
}
} else {
// 正常注册流程
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}
在Spring容器启动的过程中,会将类解析成Spring内部的BeanDefinition结构,并将BeanDefinition存储到DefaultListableBeanFactory中。
DefaultListableBeanFactory是整Spring注册及加载Bean的默认实现。
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
private volatile List<String> beanDefinitionNames = new ArrayList(256);
总结IoC容器的初始化过程:
- Resource定位(指的是BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口完成)
- BeanDefinition载入(把用户定义好的Bean表示成IoC容器内部的数据结构,即BeanDefinition)
- 向IoC容器注册BeanDefinition(BeanDefinitionRegistry)(在IoC容器内部将BeanDefinition注入到一个HashMap中,IoC容器通过HashMap持有BeanDefinition数据)
本文来自博客园,作者:白芷呀,转载请注明原文链接:https://www.cnblogs.com/angelica-duhurica/p/11185996.html