本論文では、Spring構成ファイルは、登録を処理するために解析します。
私たちは、デバッグデモへの書き込み
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("iocbeans.xml"));
复制代码
XMLリソースを取得するための最初のステップ。
第二段階は、リソースをロードすることです。
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, (BeanFactory)null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader = new XmlBeanDefinitionReader(this);
//这里才是资源加载的真正实现
this.reader.loadBeanDefinitions(resource);
}
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return this.loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
//...省略部分代码
//通过属性记录当前已经加载的资源
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 {
//获取inputStream
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if(encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//核心逻辑部分
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {//关闭流
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;
}
}
复制代码
上記は、ロジックコードをまとめたものです。
まず、着信リソース・パッケージ・パラメータと、理由コードの場合があり得ます。そして、バックを読みやすいのInputSourceオブジェクトを、準備します。最後の着信doLoadBeanDefinitions方法。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
//1.加载xml文件,转化为doc格式
Document doc = this.doLoadDocument(inputSource, resource);
//2.根据返回的doc,注册bean信息
return this.registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException var4) {
throw var4;
}
复制代码
上記1で、それはここでは無視し、XMLの検証を必要とします。
分析および登録BeanDefinitions
上記1を通じ、文書入力されたregisterBeanDefinitions(DOC、リソースを)持っています;
public int registerBeanDefinitions(Document doc, Resource resource) {
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
//记录统计前的bean个数
int countBefore = this.getRegistry().getBeanDefinitionCount();
//加载及注册bean
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
//记录本次加载bean的个数
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
复制代码
DOCは、負荷変換部は、アウトloadDocumentれるパラメータです。この方法では、オブジェクト指向の単一業務の原理の非常に良好なアプリケーションは、単一の論理処理クラスに委託され処理され、このクラスは、論理的な処理BeanDefinitionDocumentReaderあるれます。BeanDefinitionDocumentReaderはインターフェースであり、作業の例は、(行われる)createBeanDefinitionDocumentReaderにおいて、実型がDefaultBeanDefinitionDocumentReaderあるBeanDefinitionDocumentReaderこの方法により、および入力した後、再度するために、この方法の重要な目的の一つは根を抽出することであることを見出しました引数として根はBeanDefinitonの登録を続けました。
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
this.doRegisterBeanDefinitions(root);
}
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)) {
return;
}
}
}
//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)) {
return;
}
}
}
// 解析前处理,留给子类实现
this.preProcessXml(root);
this.parseBeanDefinitions(root, this.delegate);
//解析后处理,子类实现
this.postProcessXml(root);
this.delegate = parent;
}
}
复制代码
this.preProcessXml(ルート)を入力し、this.postProcessXml(ルート)メソッドは、彼らが空のメソッドあることがわかります。それが空のものを使用することである方法があるので?私たちはすぐに、これはテンプレートのデザインパターンで反映することができます。このクラスは継承のために設計された、または変更された最終を使用しますか。どちらの方法でもデザインをサブクラス化することです。
ここでは、XMLを読み始めました。
void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//对beans读取
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)) {
//对bean的处理
this.parseDefaultElement(ele, delegate);
} else {
//对bean的处理
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
复制代码
デフォルトのラベルの解析
デフォルトタグはparseDefaultElement処理機能、一目で機能の関数で解決されます。別の治療のための4つの異なるラベルの各。
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")) {
this.processBeanDefinition(ele, delegate);
} else if(delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);
}
}
复制代码
分析と登録豆タグ
上記の4つのタグ解像度のうち、最も重要かつ最も複雑なの豆のタグを解析し、我々は他のタグ解像度が解決され、彼女のアプローチを知るようになります。私たちは、コードに見えます
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//1.委托该方法进行元素解析。经过该方法,bdHolder中拥有配置文件的各种属性了。(class,name,id,alias)
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if(bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {//对解析后的bdHolder进行注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
//发出响应事件,通知相关的监听器,这个bean已经加载完成了
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
复制代码
解析BeanDefinition
まず、我々は、BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ELE)から元素分析及び情報抽出を開始し、parseBeanDefinitionElement方法BeanDefinitionParserDelegateクラスに入ります。
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute("id");//对id解析
String nameAttr = ele.getAttribute("name");//对name解析
List<String> aliases = new ArrayList();
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(containingBean == null) {
this.checkNameUniqueness(beanName, aliases, ele);
}
// 对标签其他属性的解析
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
if(beanDefinition != null) {
if(!StringUtils.hasText(beanName)) {
try {
if(containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
} else {
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);
}
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
//解析class属性
if(ele.hasAttribute("class")) {
className = ele.getAttribute("class").trim();
}
try {//解析parent属性
String parent = null;
if(ele.hasAttribute("parent")) {
parent = ele.getAttribute("parent");
}
//创建用于承载属性的GenericBeanDefinition
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
//硬编码解析默认bean的各种属性
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//提取description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//解析元数据
this.parseMetaElements(ele, bd);
//解析lookup-method
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析replaced-method
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造函数
this.parseConstructorArgElements(ele, bd);
//解析proterty子元素
this.parsePropertyElements(ele, bd);
//解析qualifier子元素
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
} catch (ClassNotFoundException var13) {
} finally {
this.parseState.pop();
}
return null;
}
复制代码
最後に、すべての属性豆タグ、我々はどのように解決を見てきました。
-
RootBeanDefiniton、ChildBeanDefinitioとGenericBeanDefinition:ベアラを作成するためBeanDefinition BeanDefinitonインターフェイスの特性である、春に実装3つが存在します。3つの実装は、コンテナラベルで表されBeanDefinitonプロファイル要素AbstractBeanDefinitionを継承しています。彼らは対応。一般的な要素のタグに対応する最も一般的な実装クラス、あるRootBeanDefinitionは、GenericBeanDefinition豆ファイルは、クラス、ワンストップ・サービス・クラスを定義して、新たに追加された構成属性です。親と子が親RootBeanDefinitonに代表される、設定ファイルで定義することができ、子供がChildBeanDefinitionで表現されますが、親がRootBeanDefiniton図を使用しないだろう。容器の内部表現にBeanDefinitionプロファイル情報によってスプリング、及びBeanDefinitionRegistryにおけるこれらBeanDefinitionを登録します。BeanDefinitionRegistryは主に追跡設定情報を直接BeanDefinitionRegistryを保存するマップの形で、ばねメモリデータベースです。即ちGenericBeanDefinitionタイプのインスタンスを作成し、プロパティを運ぶための第1のインスタンスのサブ属性を作成するために解析されるように、見ることができます。createBeanDefinition(クラス名、親)の役割は、この機能を実装することです。静的パブリックAbstractBeanDefinition createBeanDefinition(文字列parentName、文字クラス名、クラスローダクラスローダ)はClassNotFoundExceptionが{GenericBeanDefinition BD =新しいGenericBeanDefinitionを()スロー; BD。
return bd; } 复制代码
私たちは情報を運ぶBeanのインスタンスを作成したときに、さまざまな属性は、さまざまなプロパティを解決し、情報が豆を解消することができます。公共AbstractBeanDefinitionのparseBeanDefinitionAttributes(要素ELE、文字列のbeanName、BeanDefinition containingBean、AbstractBeanDefinition BD){//場合scope属性を解析(ele.hasAttribute( "シングルトン")){this.error(「旧:すべての要素のparseBeanDefinitionAttributes要素は、属性を解析されます";(スコープ "){bd.setScope(ele.getAttribute(範囲「));} - 使用中の1.1 'シングルトン' 属性は、 'スコープ' 宣言}そうならele.hasAttribute()"、ELE)" へのアップグレードそれ以外(containingBean = nullで!)場合は{bd.setScope(containingBean.getScope());}()ele.hasAttribute( "抽象的")場合//抽象的属性を解析{bd.setAbstract( "真" .equals(ELE。 getAttribute( "抽象")));} // lazyInit = ele.getAttribute( "レイジーのinit")レイジーINIT属性の文字列を解析するには、( "デフォルト" の場合。(lazyInit)){lazyInit = this.defaults.getLazyInit()に等しいです。}
bd.setLazyInit("true".equals(lazyInit)); //解析autowire属性 String autowire = ele.getAttribute("autowire"); bd.setAutowireMode(this.getAutowireMode(autowire)); //解析dependency-check属性 String dependencyCheck = ele.getAttribute("dependency-check"); bd.setDependencyCheck(this.getDependencyCheck(dependencyCheck)); String autowireCandidate; //解析depends-on属性 if(ele.hasAttribute("depends-on")) { autowireCandidate = ele.getAttribute("depends-on"); bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; ")); } //解析autowire-candidate属性 autowireCandidate = ele.getAttribute("autowire-candidate"); String destroyMethodName; if(!"".equals(autowireCandidate) && !"default".equals(autowireCandidate)) { bd.setAutowireCandidate("true".equals(autowireCandidate)); } else { destroyMethodName = this.defaults.getAutowireCandidates(); if(destroyMethodName != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } //解析primary属性 if(ele.hasAttribute("primary")) { bd.setPrimary("true".equals(ele.getAttribute("primary"))); } //解析init-method属性 if(ele.hasAttribute("init-method")) { destroyMethodName = ele.getAttribute("init-method"); if(!"".equals(destroyMethodName)) { bd.setInitMethodName(destroyMethodName); } } else if(this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } //解析destroy-method属性 if(ele.hasAttribute("destroy-method")) { destroyMethodName = ele.getAttribute("destroy-method"); bd.setDestroyMethodName(destroyMethodName); } else if(this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } //解析factory-method属性 if(ele.hasAttribute("factory-method")) { bd.setFactoryMethodName(ele.getAttribute("factory-method")); } //解析factory-bean属性 if(ele.hasAttribute("factory-bean")) { bd.setFactoryBeanName(ele.getAttribute("factory-bean")); } return bd; } 复制代码
上記処理後、春は、すべてのBeanプロパティの解析を完了しました。換言すれば、XML構成は、クラスのGenericBeanDefinitionインスタンス内のすべての対応する構成に見出すことができます。GenericBeanDefinitionだけサブクラスの実装、および一般的な属性のほとんどはにAbstractBeanDefinitionに格納されています。私たちは、このクラスを見て
//...省略静态变量以及final常量
private volatile Object beanClass;
private String scope;
private boolean abstractFlag;
private boolean lazyInit;
private int autowireMode;
private int dependencyCheck;
private String[] dependsOn;
private boolean autowireCandidate;
private boolean primary;
private final Map<String, AutowireCandidateQualifier> qualifiers;
private boolean nonPublicAccessAllowed;
private boolean lenientConstructorResolution;
private ConstructorArgumentValues constructorArgumentValues;
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides;
private String factoryBeanName;
private String factoryMethodName;
private String initMethodName;
private String destroyMethodName;
private boolean enforceInitMethod;
private boolean enforceDestroyMethod;
private boolean synthetic;
private int role;
private String description;
private Resource resource;
复制代码
解決BeanDefinitionに署名
beanDefinitionの取得は、その後の使用を満たすために持っている、とだけ残っている作業が登録されているため私たちは、コンフィギュレーション・ファイルを解析されました。私たちは、締結しました
#DefaultBeanDefinitionDocumentReader
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
//使用beanName做唯一标识注册
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);
}
}
}
复制代码
上記のコードから分かるように、レジストリに登録beanDefinition BeanDefinitioinRegistryタイプを構文解析し、登録beanDefinitionための2つの部分にする:登録および登録のBEANNAMEエイリアス。
-
マップには、キーとして本質的のbeanName、beanDefinition登録のためのbeanName BeanDefinitionを登録すること。公共ボイドregisterBeanDefinition(文字列のbeanName、BeanDefinition beanDefinition)がBeanDefinitionStoreExceptionを{スロー
if(beanDefinition instanceof AbstractBeanDefinition) { try {//最后一次校验 ((AbstractBeanDefinition)beanDefinition).validate(); } catch (BeanDefinitionValidationException var9) } } BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName); if(oldBeanDefinition != null) { //...省略 如果beanName 存在,且不允许覆盖,就抛出异常 if(!this.isAllowBeanDefinitionOverriding()) { } this.beanDefinitionMap.put(beanName, beanDefinition); } else { if(this.hasBeanCreationStarted()) { Map var4 = this.beanDefinitionMap; //加锁 放进map 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; 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);//重置所有beanName缓存 } } 复制代码
-
エイリアスは、(文字列名、文字列の別名){//のbeanNameかの別名を記録し、対応するエイリアスを削除しない場合は、同じエイリアスを持つ場合(alias.equals(名)){this.aliasMap.remove(別名)BeanDefinition公共ボイドregisterAlias登録しました;}他{ストリングregisteredName =(文字列)this.aliasMap.get(別名); IF(!registeredName = NULL){IF(registeredName.equals(名)){リターン;}
if(!this.allowAliasOverriding()) { } this.checkForAliasCircle(name, alias); //注册 this.aliasMap.put(alias, name); } } 复制代码
-