public static void main(String[] args) {XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));}
配置文件封装
new ClassPathResource("spring.xml")
Spring对于不同来源的资源文件都有响应的Resource实现
XmlBeanFactory构造
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {super(parentBeanFactory);this.reader.loadBeanDefinitions(resource);}
- super方法
/*** Create a new AbstractAutowireCapableBeanFactory.*/public AbstractAutowireCapableBeanFactory() {super();ignoreDependencyInterface(BeanNameAware.class);ignoreDependencyInterface(BeanFactoryAware.class);ignoreDependencyInterface(BeanClassLoaderAware.class);if (NativeDetector.inNativeImage()) {this.instantiationStrategy = new SimpleInstantiationStrategy();}else {this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();}}
 
- ignoreDependencyInterface(接口.clsss):会忽略指定接口的类型的依赖项
 
- reader.loadBeanDefinitions(resource)
 
重点内容,reader的实现类就是XmlBeanFactoryReader
loadBeanDefinitions(resource)
处理流程
- 将
Resource封装成EncodedResource - 从
Resource获取InputSource 最后将
Resource和InputSource共同传入doLoadBeanDefinitions方法中doLoadBeanDefinitions这段代码里异常处理很多,不看异常处理,重要的代码是2句
加载xml文件为Document
根据Document注册Bean信息
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {Document doc = doLoadDocument(inputSource, resource);int count = registerBeanDefinitions(doc, resource);return count;}catch ....}
获取Document流程
获取Document流程交给了
DocumentLoader的唯一一个实现类DefaultDocumentLoader来处理,
具体的处理逻辑也是通过Java提供的SAX对XML进行解析解析及注册BeanDefinitions
流程描述
获取一个
BeanDefinitionDocumentRader类,这里的具体实现类是DefaultBeanDefinitionDocumentReader- 调用
DefaultBeanDefinitionDocumentReader解析前,封装XmlReaderContext - 调用
DefaultBeanDefinitionDocumentReader的registerBeanDefinitions执行注册 - 
doRegisterBeanDefinitionsDefaultBeanDefinitionDocumentReader的registerBeanDefinitions最终会进入,这个doRegisterBeanDefinitions方法。@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)protected void doRegisterBeanDefinitions(Element root) {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);// We cannot use Profiles.of(...) since profile expressions are not supported// in XML config. See SPR-12458 for details.if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isDebugEnabled()) {logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}preProcessXml(root);parseBeanDefinitions(root, this.delegate);postProcessXml(root);this.delegate = parent;}
 创建委托对象
- 解析profile
 - preProcessXml:未实现的方法
 - 执行解析
 - postProcessXml:未实现的方法
parseBeanDefinitions(root, this.delegate);
解析”import”, “alias”, “bean”等元素 
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;if (delegate.isDefaultNamespace(ele)) {parseDefaultElement(ele, delegate);}else {delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}}
若是默认元素标签:bean、import、alias等,走parseDefaultElement(ele, delegate);
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {//import标签importBeanDefinitionResource(ele);}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {//alias标签processAliasRegistration(ele);}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {//bean标签processBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}}
若是自定义标签:走delegate.parseCustomElement(ele);
Bean标签的解析
方法:DefaultBeanDefinitionDocumentReader#processBeanDefinition

- 委托
BeanDefinitionDelegate类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHodler - 若默认标签的子标签下有自定义标签,会执行
BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired()方法 - 将
BeanDefinition注册,通过BeanDefinitionReaderUtils - 
步骤1解析为BeanDefinitionHodler
 判断beanName和name属性
- 生成
GenericBeanDefinition - 若无beanName,自动生成
 
@Nullablepublic BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {//提取 id 和 name属性String id = ele.getAttribute(ID_ATTRIBUTE);String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//所有的name属性通过分词作为别名List<String> aliases = new ArrayList<>();if (StringUtils.hasLength(nameAttr)) {String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);aliases.addAll(Arrays.asList(nameArr));}String beanName = id;//若未指定id则使用 name的 第一个元素作为 beanNameif (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {beanName = aliases.remove(0);if (logger.isTraceEnabled()) {logger.trace("No XML 'id' specified - using '" + beanName +"' as bean name and " + aliases + " as aliases");}}//检查所有的别名和beanName的唯一性if (containingBean == null) {checkNameUniqueness(beanName, aliases, ele);}//将元素解析未 BeanDefinitonAbstractBeanDefinition beanDefinition = 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);// 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.String beanClassName = beanDefinition.getBeanClassName();if (beanClassName != null &&beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {aliases.add(beanClassName);}}if (logger.isTraceEnabled()) {logger.trace("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);}return null;}
根据指定字符串中任一字符串分词的工具类 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
生成GenericBeanDefinition
- 解析
中的calss和parent  - 生生成BeanDefinition
 - 解析
的各种属性  - 解析子元素meta
 

- 解析子元素lookup-method
 

- 解析子元素replaced-method
 - 解析子元素constructor-arg
 - 解析子元素property
 解析子元素qualifier
@Nullablepublic AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {this.parseState.push(new BeanEntry(beanName));String className = null;if (ele.hasAttribute(CLASS_ATTRIBUTE)) {className = ele.getAttribute(CLASS_ATTRIBUTE).trim();}String parent = null;if (ele.hasAttribute(PARENT_ATTRIBUTE)) {parent = ele.getAttribute(PARENT_ATTRIBUTE);}try {AbstractBeanDefinition bd = createBeanDefinition(className, parent);//解析 parent scope/lazy-init等属性parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));//parseMetaElements(ele, bd);//解析lookupparseLookupOverrideSubElements(ele, bd.getMethodOverrides());parseReplacedMethodSubElements(ele, bd.getMethodOverrides());//解析构造函数参数parseConstructorArgElements(ele, bd);//解析属性parsePropertyElements(ele, bd);parseQualifierElements(ele, bd);bd.setResource(this.readerContext.getResource());bd.setSource(extractSource(ele));return bd;}catch (ClassNotFoundException ex) {error("Bean class [" + className + "] not found", ele, ex);}catch (NoClassDefFoundError err) {error("Class that bean class [" + className + "] depends on not found", ele, err);}catch (Throwable ex) {error("Unexpected failure during bean definition parsing", ele, ex);}finally {this.parseState.pop();}return null;}
AbstractBeanDefinition
```java
/**
- Constant for the default scope name: {@code “”}, equivalent to singleton
 status unless overridden from a parent bean definition (if applicable). */ public static final String SCOPE_DEFAULT = “”;
/**
- s自动装配模式
 - Constant that indicates no external autowiring at all.
 @see #setAutowireMode */ public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
/**
- Constant that indicates autowiring bean properties by name.
 @see #setAutowireMode */ public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
/**
- Constant that indicates autowiring bean properties by type.
 @see #setAutowireMode */ public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
/**
- Constant that indicates autowiring a constructor.
 @see #setAutowireMode */ public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
/**
- Constant that indicates determining an appropriate autowire strategy
 - through introspection of the bean class.
 - @see #setAutowireMode
 - @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
 use annotation-based autowiring for clearer demarcation of autowiring needs. */ @Deprecated public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
/**
- Constant that indicates no dependency check at all.
 @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_NONE = 0;
/**
- Constant that indicates dependency checking for object references.
 @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_OBJECTS = 1;
/**
- Constant that indicates dependency checking for “simple” properties.
 - @see #setDependencyCheck
 @see org.springframework.beans.BeanUtils#isSimpleProperty */ public static final int DEPENDENCY_CHECK_SIMPLE = 2;
/**
- Constant that indicates dependency checking for all properties
 - (object references as well as “simple” properties).
 @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_ALL = 3;
/**
- Constant that indicates the container should attempt to infer the
 - {@link #setDestroyMethodName destroy method name} for a bean as opposed to
 - explicit specification of a method name. The value {@value} is specifically
 - designed to include characters otherwise illegal in a method name, ensuring
 - no possibility of collisions with legitimately named methods having the same
 - name.
 Currently, the method names detected during destroy method inference
are “close” and “shutdown”, if present on the specific bean class. */ public static final String INFER_METHOD = “(inferred)”;
// beanClass @Nullable private volatile Object beanClass; //作用域 @Nullable private String scope = SCOPE_DEFAULT;
private boolean abstractFlag = false;
//懒加载 @Nullable private Boolean lazyInit; //自动装配方式 private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE; //dependon @Nullable private String[] dependsOn; //装配候选人 private boolean autowireCandidate = true; // 是否主要 private boolean primary = false; // private final Map
qualifiers = new LinkedHashMap<>(); @Nullable private Supplier<?> instanceSupplier;
private boolean nonPublicAccessAllowed = true;
private boolean lenientConstructorResolution = true;
@Nullable private String factoryBeanName;
@Nullable private String factoryMethodName;
@Nullable private ConstructorArgumentValues constructorArgumentValues;
@Nullable private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides = new MethodOverrides();
@Nullable private String initMethodName;
@Nullable private String destroyMethodName;
private boolean enforceInitMethod = true;
private boolean enforceDestroyMethod = true;
private boolean synthetic = false;
private int role = BeanDefinition.ROLE_APPLICATION;
@Nullable private String description;
@Nullable private Resource resource;
<a name="PMzub"></a>## 步骤2解析自定义标签过<a name="WL1Fm"></a>## 步骤3注册成为BeanDefinition通过`BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,getReaderContext().getRegistry())`进行注册```javapublic static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any. beanName的别名String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}}
注册beanName->BeanDefinition
@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {//校验if (beanDefinition instanceof AbstractBeanDefinition) {try {((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}//若存在,需要判断是否允许覆盖BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);}else if (existingDefinition.getRole() < beanDefinition.getRole()) {// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (logger.isInfoEnabled()) {logger.info("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +existingDefinition + "] with [" + beanDefinition + "]");}}else if (!beanDefinition.equals(existingDefinition)) {if (logger.isDebugEnabled()) {logger.debug("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}else {if (logger.isTraceEnabled()) {logger.trace("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}this.beanDefinitionMap.put(beanName, beanDefinition);}else {//r若已经又Bean创建了if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)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;removeManualSingletonName(beanName);}}else {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);removeManualSingletonName(beanName);}this.frozenBeanDefinitionNames = null;}if (existingDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}else if (isConfigurationFrozen()) {clearByTypeCache();}}
注册alia->beanName
@Overridepublic void registerAlias(String name, String alias) {Assert.hasText(name, "'name' must not be empty");Assert.hasText(alias, "'alias' must not be empty");synchronized (this.aliasMap) {if (alias.equals(name)) {this.aliasMap.remove(alias);if (logger.isDebugEnabled()) {logger.debug("Alias definition '" + alias + "' ignored since it points to same name");}}else {String registeredName = this.aliasMap.get(alias);if (registeredName != null) {if (registeredName.equals(name)) {// An existing alias - no need to re-registerreturn;}if (!allowAliasOverriding()) {throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +name + "': It is already registered for name '" + registeredName + "'.");}if (logger.isDebugEnabled()) {logger.debug("Overriding alias '" + alias + "' definition for registered name '" +registeredName + "' with new target name '" + name + "'");}}checkForAliasCircle(name, alias);this.aliasMap.put(alias, name);if (logger.isTraceEnabled()) {logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");}}}}
会检查循环的问题 A->B->A
步骤4通知注册完成
过
