這篇文章將為大家詳細(xì)講解有關(guān)Java中Spring-IOC容器是什么,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供雁塔網(wǎng)站建設(shè)、雁塔做網(wǎng)站、雁塔網(wǎng)站設(shè)計(jì)、雁塔網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、雁塔企業(yè)網(wǎng)站模板建站服務(wù),10年雁塔做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
Spring IoC容器對(duì)Bean定義資源的載入是從refresh()函數(shù)開始的,refresh()是一個(gè)模板方法,refresh()方法的作用是:在創(chuàng)建IoC容器前,如果已經(jīng)有容器存在,則需要把已有的容器銷毀和關(guān)閉,以保證在refresh之后使用的是新建立起來的IoC容器。refresh的作用類似于對(duì)IoC容器的重啟,在新建立好的容器中對(duì)容器進(jìn)行初始化,對(duì)Bean定義資源進(jìn)行載入
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
//調(diào)用容器準(zhǔn)備刷新的方法,獲取容器的當(dāng)時(shí)時(shí)間,同時(shí)給容器設(shè)置同步標(biāo)識(shí)
this.prepareRefresh();
//告訴子類啟動(dòng)refreshBeanFactory()方法,Bean定義資源文件的載入從
//子類的refreshBeanFactory()方法啟動(dòng)
//這個(gè)bean的載入過程 包括對(duì)xml的解析和加載為BeanDefinitions 都是從this.obtainFreshBeanFactory()這里進(jìn)入
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
/*這之后的代碼都是注冊容器的信息源和生命周期事件*/
//為BeanFactory配置容器特性,例如類加載器、事件處理器等
this.prepareBeanFactory(beanFactory);
try {
//為容器的某些子類指定特殊的BeanPost事件處理器
this.postProcessBeanFactory(beanFactory);
//調(diào)用所有注冊的BeanFactoryPostProcessor的Bean
this.invokeBeanFactoryPostProcessors(beanFactory);
//為BeanFactory注冊BeanPost事件處理器.
//BeanPostProcessor是Bean后置處理器,用于監(jiān)聽容器觸發(fā)的事件
this.registerBeanPostProcessors(beanFactory);
//初始化信息源,和國際化相關(guān).
this.initMessageSource();
//初始化容器事件傳播器.
this.initApplicationEventMulticaster();
//調(diào)用子類的某些特殊Bean初始化方法
this.onRefresh();
//為事件傳播器注冊事件監(jiān)聽器.
this.registerListeners();
//初始化所有剩余的單態(tài)Bean.
this.finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件處理器,并發(fā)布容器的生命周期事件
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//銷毀以創(chuàng)建的單態(tài)Bean
this.destroyBeans();
//取消refresh操作,重置容器的同步標(biāo)識(shí).
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}AbstractRefreshableApplicationContext 類:
AbstractRefreshableApplicationContext中只定義了抽象的loadBeanDefinitions方法,容器真正調(diào)用的是其子類AbstractXmlApplicationContext對(duì)該方法的實(shí)現(xiàn)
protected final void refreshBeanFactory() throws BeansException {
//如果已經(jīng)創(chuàng)建了BeanFactory,則銷毀并關(guān)閉BeanFactory
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
//創(chuàng)建了一個(gè)IOC容器
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
/對(duì)IoC容器進(jìn)行定制化,如設(shè)置啟動(dòng)參數(shù),開啟注解的自動(dòng)裝配等
this.customizeBeanFactory(beanFactory);
//調(diào)用載入Bean定義的方法,主要這里又使用了一個(gè)委派模式,在當(dāng)前類中只定義了抽象的loadBeanDefinitions方法,具體的實(shí)現(xiàn)調(diào)用子類容器
this.loadBeanDefinitions(beanFactory);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}AbstractXmlApplicationContext 類:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//創(chuàng)建XmlBeanDefinitionReader,即創(chuàng)建Bean讀取器,并通過回調(diào)設(shè)置到容器中去,容器使用該讀取器讀取Bean定義資源
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
//為Bean讀取器設(shè)置Spring資源加載器,AbstractXmlApplicationContext的
//祖先父類AbstractApplicationContext繼承DefaultResourceLoader,因此,容器本身也是一個(gè)資源加載器
beanDefinitionReader.setResourceLoader(this);
//為Bean讀取器設(shè)置SAX xml解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//當(dāng)Bean讀取器讀取Bean定義的Xml資源文件時(shí),啟用Xml的校驗(yàn)機(jī)制
this.initBeanDefinitionReader(beanDefinitionReader);
//Bean讀取器真正實(shí)現(xiàn)加載的方法
this.loadBeanDefinitions(beanDefinitionReader);
}
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
reader.setValidating(this.validating);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = this.getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
@Nullable
protected Resource[] getConfigResources() {
return null;
}在其抽象父類AbstractBeanDefinitionReader中定義了載入過程
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//獲取resourceLoader
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
} else {
int loadCount;
if (!(resourceLoader instanceof ResourcePatternResolver)) {
//將指定位置的Bean定義資源文件解析為Spring IoC容器封裝的資源
//加載多個(gè)指定位置的Bean定義資源文件 完成具體的資源定位的工作
Resource resource = resourceLoader.getResource(location);
//加載資源 開始我們的第二步操作 轉(zhuǎn)換為BeanDefinition對(duì)象
loadCount = this.loadBeanDefinitions((Resource)resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
} else {
try {
//將指定位置的Bean定義資源文件解析為Spring IoC容器封裝的資源
//加載單個(gè)指定位置的Bean定義資源文件
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
//加載資源 開始我們的第二步操作 轉(zhuǎn)換為BeanDefinition對(duì)象
loadCount = this.loadBeanDefinitions(resources);
if (actualResources != null) {
Resource[] var6 = resources;
int var7 = resources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource resource = var6[var8];
actualResources.add(resource);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
} catch (IOException var10) {
throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
}
}
}
}具體加載資源的方法
首先,調(diào)用資源加載器的獲取資源方法resourceLoader.getResource(location),獲取到要加載的資源。
其次,真正執(zhí)行加載功能是其子類XmlBeanDefinitionReader的loadBeanDefinitions方法。
資源定位到這里就結(jié)束 最終返回的是一個(gè)Resource的對(duì)象來進(jìn)行BeanDefinition的載入。在定位完成后,為BeanDefinition的載入創(chuàng)客I/O條件,
但是具體的載入還沒有開始載入。
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);
}
//帶有classpath標(biāo)識(shí)的Resource
if (location.startsWith("classpath:")) {
return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
}
try {
//處理URL標(biāo)識(shí)的Resource定位
URL url = new URL(location);
return (Resource)(ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
} catch (MalformedURLException var5) {
//如果不存classpath、Url、/標(biāo)志的 就教給他處理
return this.getResourceByPath(location);
}
}
ProtocolResolver protocolResolver = (ProtocolResolver)var2.next();
resource = protocolResolver.resolve(location, this);
} while(resource == null);
return resource;
}protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
//這里使用文件系統(tǒng)資源對(duì)象來定義bean 文件
return new FileSystemResource(path);
}BeanDefinition的載入分成兩部分,首先通過XML的解析器得到document對(duì)象,
但這些document對(duì)象沒有按照spring的Bean規(guī)則進(jìn)行解析。在完成XML解析后,才是按照Spring的Bean規(guī)則進(jìn)行解析,這個(gè)解析的過程是在documentReader實(shí)現(xiàn)。
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//獲取resourceLoader
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
} else {
int loadCount;
if (!(resourceLoader instanceof ResourcePatternResolver)) {
//將指定位置的Bean定義資源文件解析為Spring IoC容器封裝的資源
//加載多個(gè)指定位置的Bean定義資源文件 完成具體的資源定位的工作
Resource resource = resourceLoader.getResource(location);
//加載資源 開始我們的第二步操作 轉(zhuǎn)換為BeanDefinition對(duì)象
loadCount = this.loadBeanDefinitions((Resource)resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
} else {
try {
//將指定位置的Bean定義資源文件解析為Spring IoC容器封裝的資源
//加載單個(gè)指定位置的Bean定義資源文件
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
//加載資源 開始我們的第二步操作 轉(zhuǎn)換為BeanDefinition對(duì)象
loadCount = this.loadBeanDefinitions(resources);
if (actualResources != null) {
Resource[] var6 = resources;
int var7 = resources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource resource = var6[var8];
actualResources.add(resource);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
} catch (IOException var10) {
throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
}
}
}
}xml文件轉(zhuǎn)換為document對(duì)象 再解析BeanDefinition
這里是載入XML形式Bean定義資源文件方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if(this.logger.isInfoEnabled()) {
this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
if(currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if(!((Set)currentResources).add(encodedResource)) {
throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
} else {
int var5;
try {
//將資源文件轉(zhuǎn)為InputStream的IO流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//從InputStream中得到XML的解析源
InputSource inputSource = new InputSource(inputStream);
if(encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//這里是具體的讀取過程
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
//IO流的關(guān)閉
inputStream.close();
}
} catch (IOException var15) {
throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
} finally {
((Set)currentResources).remove(encodedResource);
if(((Set)currentResources).isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
return var5;
}
} protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
//@1將XML文件轉(zhuǎn)換為DOM對(duì)象,解析過程由documentLoader實(shí)現(xiàn)
Document doc = this.doLoadDocument(inputSource, resource);
//@2這里是啟動(dòng)對(duì)Bean定義解析的詳細(xì)過程,該解析過程會(huì)用到Spring的Bean配置規(guī)則
return this.registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException var4) {
throw var4;
} catch (SAXParseException var5) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var5.getLineNumber() + " in XML document from " + resource + " is invalid", var5);
} catch (SAXException var6) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var6);
} catch (ParserConfigurationException var7) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var7);
} catch (IOException var8) {
throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var8);
} catch (Throwable var9) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var9);
}
}@1
//使用標(biāo)準(zhǔn)的JAXP將載入的Bean定義資源轉(zhuǎn)換成document對(duì)象
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
//創(chuàng)建文件解析器工廠
DocumentBuilderFactory factory = this.createDocumentBuilderFactory(validationMode, namespaceAware);
if(logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
//創(chuàng)建文檔解析器
DocumentBuilder builder = this.createDocumentBuilder(factory, entityResolver, errorHandler);
//解析Spring的Bean定義資源
return builder.parse(inputSource);
}
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware) throws ParserConfigurationException {
//創(chuàng)建文檔解析工廠
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(namespaceAware);
if(validationMode != 0) {
//設(shè)置解析XML的校驗(yàn)
factory.setValidating(true);
if(validationMode == 3) {
factory.setNamespaceAware(true);
try {
factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
} catch (IllegalArgumentException var6) {
ParserConfigurationException pcex = new ParserConfigurationException("Unable to validate using XSD: Your JAXP provider [" + factory + "] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
pcex.initCause(var6);
throw pcex;
}
}
}
return factory;
}Spring IoC容器根據(jù)定位的Bean定義資源文件,將其加載讀入并轉(zhuǎn)換成為Document對(duì)象過程完成。
下面是 Spring IoC容器將載入的Bean定義資源文件轉(zhuǎn)換為Document對(duì)象之后,是如何將其解析為Spring IoC管理的Bean對(duì)象并將其注冊到容器中的
@2
//按照Spring的Bean語義要求將Bean定義資源解析并轉(zhuǎn)換為容器內(nèi)部數(shù)據(jù)結(jié)構(gòu)
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
/得到BeanDefinitionDocumentReader來對(duì)xml格式的BeanDefinition解析
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
//獲得容器中注冊的Bean數(shù)量
int countBefore = this.getRegistry().getBeanDefinitionCount();
//解析過程入口,這里使用了委派模式,BeanDefinitionDocumentReader只是個(gè)接口
//具體的解析實(shí)現(xiàn)過程有實(shí)現(xiàn)類DefaultBeanDefinitionDocumentReader完成
//@1
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
/統(tǒng)計(jì)解析的Bean數(shù)量
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
//創(chuàng)建BeanDefinitionDocumentReader對(duì)象,解析Document對(duì)象
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return (BeanDefinitionDocumentReader)BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}DefaultBeanDefinitionDocumentReader 解析document對(duì)象按照spring Bean的定義規(guī)則轉(zhuǎn)換為BeanDefinition
@1
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
public static final String BEAN_ELEMENT = "bean";
public static final String NESTED_BEANS_ELEMENT = "beans";
public static final String ALIAS_ELEMENT = "alias";
public static final String NAME_ATTRIBUTE = "name";
public static final String ALIAS_ATTRIBUTE = "alias";
public static final String IMPORT_ELEMENT = "import";
public static final String RESOURCE_ATTRIBUTE = "resource";
public static final String PROFILE_ATTRIBUTE = "profile";
protected final Log logger = LogFactory.getLog(this.getClass());
private XmlReaderContext readerContext;
private BeanDefinitionParserDelegate delegate;
public DefaultBeanDefinitionDocumentReader() {
}
//根據(jù)Spring DTD對(duì)Bean的定義規(guī)則解析Bean定義Document對(duì)象
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
//獲得XML描述符
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
//獲得Document的根元素
Element root = doc.getDocumentElement();
this.doRegisterBeanDefinitions(root);
}
protected final XmlReaderContext getReaderContext() {
return this.readerContext;
}
protected Object extractSource(Element ele) {
return this.getReaderContext().extractSource(ele);
}
//具體的解析過程由BeanDefinitionParserDelegate實(shí)現(xiàn),
//BeanDefinitionParserDelegate中定義了Spring Bean定義XML文件的各種元素
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
if(this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute("profile");
if(StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if(this.logger.isInfoEnabled()) {
this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
}
return;
}
}
}
//在解析Bean定義之前,進(jìn)行自定義的解析,增強(qiáng)解析過程的可擴(kuò)展性
this.preProcessXml(root);
//從Document的根元素開始進(jìn)行Bean定義的Document對(duì)象
this.parseBeanDefinitions(root, this.delegate);
//在解析Bean定義之后,進(jìn)行自定義的解析,增加解析過程的可擴(kuò)展性
this.postProcessXml(root);
this.delegate = parent;
}
//創(chuàng)建BeanDefinitionParserDelegate,用于完成真正的解析過程
protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
//BeanDefinitionParserDelegate初始化Document根元素
delegate.initDefaults(root, parentDelegate);
return delegate;
}
//使用Spring的Bean規(guī)則從Document的根元素開始進(jìn)行Bean定義的Document對(duì)象
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//Bean定義的Document對(duì)象使用了Spring默認(rèn)的XML命名空間
if(delegate.isDefaultNamespace(root)) {
//獲取Bean定義的Document對(duì)象根元素的所有子節(jié)點(diǎn)
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//獲得Document節(jié)點(diǎn)是XML元素節(jié)點(diǎn)
if(node instanceof Element) {
Element ele = (Element)node;
//Bean定義的Document的元素節(jié)點(diǎn)使用的是Spring默認(rèn)的XML命名空間
if(delegate.isDefaultNamespace(ele)) {
//使用Spring的Bean規(guī)則解析元素節(jié)點(diǎn)
this.parseDefaultElement(ele, delegate);
} else {
//沒有使用Spring默認(rèn)的XML命名空間,則使用用戶自定義的解//析規(guī)則解析元素節(jié)點(diǎn)
delegate.parseCustomElement(ele);
}
}
}
} else {
//Document的根節(jié)點(diǎn)沒有使用Spring默認(rèn)的命名空間,則使用用戶自定義的
//解析規(guī)則解析Document根節(jié)點(diǎn)
delegate.parseCustomElement(root);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//如果元素節(jié)點(diǎn)是<Import>導(dǎo)入元素,進(jìn)行導(dǎo)入解析
if(delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);
} else if(delegate.nodeNameEquals(ele, "alias")) {
//如果元素節(jié)點(diǎn)是<Alias>別名元素,進(jìn)行別名解析
this.processAliasRegistration(ele);
} else if(delegate.nodeNameEquals(ele, "bean")) {
//元素節(jié)點(diǎn)既不是導(dǎo)入元素,也不是別名元素,即普通的<Bean>元素,
//按照Spring的Bean規(guī)則解析元素
this.processBeanDefinition(ele, delegate);
} else if(delegate.nodeNameEquals(ele, "beans")) {
//如果元素節(jié)點(diǎn)是<beans>元素注冊為BeanDefintion
this.doRegisterBeanDefinitions(ele);
}
}
//解析<Import>導(dǎo)入元素,從給定的導(dǎo)入路徑加載Bean定義資源到Spring IoC容器中
protected void importBeanDefinitionResource(Element ele) {
/獲取給定的導(dǎo)入元素的location屬性
String location = ele.getAttribute("resource");
if(!StringUtils.hasText(location)) {
this.getReaderContext().error("Resource location must not be empty", ele);
} else {
//獲取location的值
location = this.getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet(4);
//標(biāo)識(shí)給定的導(dǎo)入元素的location是否是絕對(duì)路徑
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
} catch (URISyntaxException var11) {
;
}
int importCount;
if(absoluteLocation) {
try {
//使用資源讀入器加載給定路徑的Bean定義資源
importCount = this.getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
} catch (BeanDefinitionStoreException var10) {
this.getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, var10);
}
} else {
//給定的導(dǎo)入元素的location是相對(duì)路徑
try {
Resource relativeResource = this.getReaderContext().getResource().createRelative(location);
if(relativeResource.exists()) {
//使用資源讀入器加載Bean定義資源
importCount = this.getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
} else {
String baseLocation = this.getReaderContext().getResource().getURL().toString();
importCount = this.getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
} catch (IOException var8) {
this.getReaderContext().error("Failed to resolve current resource location", ele, var8);
} catch (BeanDefinitionStoreException var9) {
this.getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, var9);
}
}
//在解析完<Import>元素之后,發(fā)送容器導(dǎo)入其他資源處理完成事件
Resource[] actResArray = (Resource[])actualResources.toArray(new Resource[actualResources.size()]);
this.getReaderContext().fireImportProcessed(location, actResArray, this.extractSource(ele));
}
}
//解析<Alias>別名元素,為Bean向Spring IoC容器注冊別名
protected void processAliasRegistration(Element ele) {
//獲取<Alias>別名元素中name的屬性值
String name = ele.getAttribute("name");
//獲取<Alias>別名元素中alias的屬性值
String alias = ele.getAttribute("alias");
boolean valid = true;
if(!StringUtils.hasText(name)) {
this.getReaderContext().error("Name must not be empty", ele);
valid = false;
}
if(!StringUtils.hasText(alias)) {
this.getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if(valid) {
try {
//向容器的資源讀入器注冊別名
this.getReaderContext().getRegistry().registerAlias(name, alias);
} catch (Exception var6) {
this.getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, var6);
}
//在解析完<Alias>元素之后,發(fā)送容器別名處理完成事件
this.getReaderContext().fireAliasRegistered(name, alias, this.extractSource(ele));
}
}
//解析Bean定義資源Document對(duì)象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder是對(duì)BeanDefinition的封裝,即Bean定義的封裝類
//對(duì)Document對(duì)象中<Bean>元素的解析由BeanDefinitionParserDelegate實(shí)現(xiàn) BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//向Spring IoC容器注冊解析得到的Bean定義,這是Bean定義向IoC容器注冊的入口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
//在完成向Spring IoC容器注冊解析得到的Bean定義之后,發(fā)送注冊事件
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
protected void preProcessXml(Element root) {
}
protected void postProcessXml(Element root) {
}
}通過上述Spring IoC容器對(duì)載入的Bean定義Document解析可以看出,我們使用Spring時(shí),在Spring配置文件中可以使用<Import>元素來導(dǎo)入IoC容器所需要的其他資源,Spring IoC容器在解析時(shí)會(huì)首先將指定導(dǎo)入的資源加載進(jìn)容器中。使用<Ailas>別名時(shí),Spring IoC容器首先將別名元素所定義的別名注冊到容器中。
對(duì)于既不是<Import>元素,又不是<Alias>元素的元素,即Spring配置文件中普通的<Bean>元素的解析由BeanDefinitionParserDelegate類的parseBeanDefinitionElement方法來實(shí)現(xiàn)。
下面是針對(duì)對(duì)Bean元素的解析過程
//解析Bean定義資源文件中的<Bean>元素,這個(gè)方法中主要處理<Bean>元素的id,name
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//獲取id屬性
String id = ele.getAttribute("id");
//獲取name屬性
String nameAttr = ele.getAttribute("name");
List<String> aliases = new ArrayList();
//將Bean元素的name屬性全部放到alias屬性里面
if(StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if(!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if(this.logger.isDebugEnabled()) {
this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
if(containingBean == null) {
//檢查bean元素的id和name是否是唯一的
this.checkNameUniqueness(beanName, aliases, ele);
}
//詳細(xì)對(duì)<Bean>元素中配置的Bean定義進(jìn)行解析的地方
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
if(beanDefinition != null) {
if(!StringUtils.hasText(beanName)) {
try {
if(containingBean != null) {
//判斷如果沒有id和name屬性時(shí)候是否包含子元素的<Bean>
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
} else {
//如果<Bean>元素中沒有配置id、別名或者name,且包含了子//<Bean>元素,為解析的Bean使用別名向IoC容器注冊
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if(beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if(this.logger.isDebugEnabled()) {
this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
//詳細(xì)解析bean元素的地方
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
//是否包含class屬性
if(ele.hasAttribute("class")) {
//獲取class屬性值 不做實(shí)例化,bean的實(shí)例化是在第一次獲取bean的時(shí)候完成,這里只獲取class的值
className = ele.getAttribute("class").trim();
}
try {
String parent = null;
//如果<Bean>元素中配置了parent屬性,則獲取parent屬性的值
if(ele.hasAttribute("parent")) {
parent = ele.getAttribute("parent");
}
//根據(jù)<Bean>元素配置的class名稱和parent屬性值創(chuàng)建BeanDefinition
//為載入Bean定義信息做準(zhǔn)備
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
//對(duì)當(dāng)前的<Bean>元素中配置的一些屬性進(jìn)行解析和設(shè)置,如配置的單態(tài)(singleton)屬性等
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//為<Bean>元素解析的Bean設(shè)置description信息 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//對(duì)<Bean>元素的meta(元信息)屬性解析
this.parseMetaElements(ele, bd);
//對(duì)<Bean>元素的lookup-method屬性解析
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//對(duì)<Bean>元素的replaced-method屬性解析
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析<Bean>元素的構(gòu)造方法設(shè)置
this.parseConstructorArgElements(ele, bd);
//解析<Bean>元素的<property>設(shè)置
this.parsePropertyElements(ele, bd);
//解析<Bean>元素的qualifier屬性
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
} catch (ClassNotFoundException var13) {
this.error("Bean class [" + className + "] not found", ele, var13);
} catch (NoClassDefFoundError var14) {
this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
} catch (Throwable var15) {
this.error("Unexpected failure during bean definition parsing", ele, var15);
} finally {
this.parseState.pop();
}
return null;
}通過對(duì)上述源碼的分析,就會(huì)明白我們在Spring配置文件中<Bean>元素的中配置的屬性就是通過該方法解析和設(shè)置到Bean中去的。
注意:在解析<Bean>元素過程中沒有創(chuàng)建和實(shí)例化Bean對(duì)象,只是創(chuàng)建了Bean對(duì)象的定義類BeanDefinition,將<Bean>元素中的配置信息設(shè)置到BeanDefinition中作為記錄,當(dāng)依賴注入時(shí)才使用這些記錄信息創(chuàng)建和實(shí)例化具體的Bean對(duì)象。
上面方法中一些對(duì)一些配置如元信息(meta)、qualifier等的解析,我們在Spring中配置時(shí)使用的也不多,我們在使用Spring的<Bean>元素時(shí),配置最多的是<property>屬性。
調(diào)用BeanDefinitionReaderUtils的registerBeanDefinition方法向IoC容器注冊解析的Bean
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null) {
//通過對(duì)document對(duì)象的解析和封裝返回一個(gè)BeanDefinitionHolder
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//通過這個(gè)holder來注冊bean對(duì)象
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));
}
}當(dāng)調(diào)用BeanDefinitionReaderUtils向IoC容器注冊解析的BeanDefinition時(shí),真正完成注冊功能的是DefaultListableBeanFactory。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if(aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}DefaultListableBeanFactory registerBeanDefinition方法
//存儲(chǔ)注冊的俄BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
//向IoC容器注冊解析的BeanDefiniton
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//校驗(yàn)解析的BeanDefiniton
if(beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if(oldBeanDefinition != null) {
if(!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if(!beanDefinition.equals(oldBeanDefinition)) {
if(this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if(this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if(this.hasBeanCreationStarted()) {
Map var4 = this.beanDefinitionMap;
//注冊的過程中需要線程同步,以保證數(shù)據(jù)的一致性
synchronized(this.beanDefinitionMap) {
//把bean存放到map中
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 {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if(oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}至此,Bean定義資源文件中配置的Bean被解析過后,已經(jīng)注冊到IoC容器中,被容器管理起來,真正完成了IoC容器初始化所做的全部工作。現(xiàn) 在IoC容器中已經(jīng)建立了整個(gè)Bean的配置信息,這些BeanDefinition信息已經(jīng)可以使用,并且可以被檢索,IoC容器的作用就是對(duì)這些注冊的Bean定義信息進(jìn)行處理和維護(hù)。這些的注冊的Bean定義信息是IoC容器控制反轉(zhuǎn)的基礎(chǔ),正是有了這些注冊的數(shù)據(jù),容器才可以進(jìn)行依賴注入。
關(guān)于Java中Spring-IOC容器是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
文章題目:Java中Spring-IOC容器是什么
文章轉(zhuǎn)載:http://chinadenli.net/article20/pgjoco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、關(guān)鍵詞優(yōu)化、做網(wǎng)站、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)