Resources
将不同来源的资源抽象成URL,通过注册不同的handler来处理不同来源的资源的读取逻辑。
Resouces接口抽象了所有Spring内部使用到的底层资源。
在resource加载了配置文件之后,将读取配置文件的工作交给了后续的XXXReader。
例子
XmlBeanFactory
1.Resource 获取配置文件资源
2.构造XmlBeanDefinitionReader
3.获取inputStream并构造InputResource
4.调用核心方法doLoadBeanDefinitions
this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
doLoadBeanDefinitions(){
1.获取对XML文件的验证模式。
getValidationModeForResource
2.加载XML文件,并得到对应的Document。
this.doLoadDocument(inputSource, resource);
3.根据返回的Document注册Bean信息。
this.registerBeanDefinitions(doc, resource);
}
registerBeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建子类,DefaultBeanDefinitionDocumentReader
//BeanDefinitionDocumentReader 重要的在于提取root
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
int countBefore = this.getRegistry().getBeanDefinitionCount();
//此处的registerBeanDefinitions其实是调用BeanDefinitionDocumentReader的doRegisterBeanDefinitions()
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
doRegisterBeanDefinitions
核心解析类
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, ",; ");
//应该是判断当前的环境是否支持这种profile
if (!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
}
return;
}
}
}
//空实现 ,模板方法 ,交给子类选择处理
this.preProcessXml(root);
//核心解析类
this.parseBeanDefinitions(root, this.delegate);
//空实现 ,模板方法 ,交给子类选择处理
this.postProcessXml(root);
this.delegate = parent;
}
parseBeanDefinitions
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;
//判断如果是默认的标签,则使用默认的解析方法
//里面有对四种标签属性的解析 import alias bean beans 最常用的为this.processBeanDefinition(ele, delegate);
if (delegate.isDefaultNamespace(ele)) {
this.parseDefaultElement(ele, delegate);
} else {
/否则使用用户自定义的解析方法
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//此处完成了对XML的标签解析,包括bean的id,name.....
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//bean使用了默认解析方法,但是属性却使用了自定义的标签
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//将解析完的BeanDeginition注册到BeanDeginitionRegistry
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));
}
}
registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry())
注册BeanDeginition
registry.registerBeanDefinition主要步骤如下:
1.对AbstractBeanDefinition的校验。
2.对beanName已经注册的情况的处理,如果bean不允许被覆盖,则抛出异常,否则直接覆盖。
3.加入map缓存(ConcurrentHashMap,预防并发问题)
4.清除解析之前留下的对应beanName的缓存。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
//使用beanName注册BeanDefinition
//主要逻辑为将beanDefinition放入map中,beanName作为key
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
AbstractBeanDefinition里面定了了大量的属性。
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable {
public static final String SCOPE_DEFAULT = "";
public static final int AUTOWIRE_NO = 0;
public static final int AUTOWIRE_BY_NAME = 1;
public static final int AUTOWIRE_BY_TYPE = 2;
public static final int AUTOWIRE_CONSTRUCTOR = 3;
/** @deprecated */
@Deprecated
public static final int AUTOWIRE_AUTODETECT = 4;
public static final int DEPENDENCY_CHECK_NONE = 0;
public static final int DEPENDENCY_CHECK_OBJECTS = 1;
public static final int DEPENDENCY_CHECK_SIMPLE = 2;
public static final int DEPENDENCY_CHECK_ALL = 3;
public static final String INFER_METHOD = "(inferred)";
@Nullable
private volatile Object beanClass;
//bean的作用域
@Nullable
private String scope;
private boolean abstractFlag;
//是否懒加载
@Nullable
private Boolean lazyInit;
private int autowireMode;
private int dependencyCheck;
@Nullable
private String[] dependsOn;
private boolean autowireCandidate;
private boolean primary;
private final Map<String, AutowireCandidateQualifier> qualifiers;
@Nullable
private Supplier<?> instanceSupplier;
private boolean nonPublicAccessAllowed;
private boolean lenientConstructorResolution;
@Nullable
private String factoryBeanName;
@Nullable
private String factoryMethodName;
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
@Nullable
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides;
@Nullable
private String initMethodName;
@Nullable
private String destroyMethodName;
private boolean enforceInitMethod;
private boolean enforceDestroyMethod;
private boolean synthetic;
private int role;
@Nullable
private String description;
@Nullable
private Resource resource;
......
}