1. public static void main(String[] args) {
  2. XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));
  3. }

image.png

配置文件封装

new ClassPathResource("spring.xml")

Spring对于不同来源的资源文件都有响应的Resource实现

XmlBeanFactory构造

  1. public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
  2. super(parentBeanFactory);
  3. this.reader.loadBeanDefinitions(resource);
  4. }
  1. super方法
    1. /**
    2. * Create a new AbstractAutowireCapableBeanFactory.
    3. */
    4. public AbstractAutowireCapableBeanFactory() {
    5. super();
    6. ignoreDependencyInterface(BeanNameAware.class);
    7. ignoreDependencyInterface(BeanFactoryAware.class);
    8. ignoreDependencyInterface(BeanClassLoaderAware.class);
    9. if (NativeDetector.inNativeImage()) {
    10. this.instantiationStrategy = new SimpleInstantiationStrategy();
    11. }
    12. else {
    13. this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
    14. }
    15. }
  • ignoreDependencyInterface(接口.clsss):会忽略指定接口的类型的依赖项
  1. reader.loadBeanDefinitions(resource)

重点内容,reader的实现类就是XmlBeanFactoryReader

loadBeanDefinitions(resource)

image.png

处理流程

  1. Resource封装成EncodedResource
  2. Resource获取InputSource
  3. 最后将ResourceInputSource共同传入doLoadBeanDefinitions方法中

    doLoadBeanDefinitions

    这段代码里异常处理很多,不看异常处理,重要的代码是2句

  4. 加载xml文件为Document

  5. 根据Document注册Bean信息

    1. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    2. throws BeanDefinitionStoreException {
    3. try {
    4. Document doc = doLoadDocument(inputSource, resource);
    5. int count = registerBeanDefinitions(doc, resource);
    6. return count;
    7. }
    8. catch ....
    9. }

    获取Document流程

    获取Document流程交给了DocumentLoader的唯一一个实现类DefaultDocumentLoader来处理,
    具体的处理逻辑也是通过Java提供的SAX对XML进行解析

    解析及注册BeanDefinitions

    流程描述

  6. 获取一个BeanDefinitionDocumentRader类,这里的具体实现类是DefaultBeanDefinitionDocumentReader

  7. 调用DefaultBeanDefinitionDocumentReader解析前,封装XmlReaderContext
  8. 调用DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions执行注册
  9. 返回注册BeanDefinition数量

    doRegisterBeanDefinitions

    DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions最终会进入,这个
    doRegisterBeanDefinitions方法。

    1. @SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)
    2. protected void doRegisterBeanDefinitions(Element root) {
    3. BeanDefinitionParserDelegate parent = this.delegate;
    4. this.delegate = createDelegate(getReaderContext(), root, parent);
    5. if (this.delegate.isDefaultNamespace(root)) {
    6. String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
    7. if (StringUtils.hasText(profileSpec)) {
    8. String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
    9. profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    10. // We cannot use Profiles.of(...) since profile expressions are not supported
    11. // in XML config. See SPR-12458 for details.
    12. if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
    13. if (logger.isDebugEnabled()) {
    14. logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
    15. "] not matching: " + getReaderContext().getResource());
    16. }
    17. return;
    18. }
    19. }
    20. }
    21. preProcessXml(root);
    22. parseBeanDefinitions(root, this.delegate);
    23. postProcessXml(root);
    24. this.delegate = parent;
    25. }
  10. 创建委托对象

  11. 解析profile
  12. preProcessXml:未实现的方法
  13. 执行解析
  14. postProcessXml:未实现的方法

    parseBeanDefinitions(root, this.delegate);

    解析”import”, “alias”, “bean”等元素
  1. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
  2. if (delegate.isDefaultNamespace(root)) {
  3. NodeList nl = root.getChildNodes();
  4. for (int i = 0; i < nl.getLength(); i++) {
  5. Node node = nl.item(i);
  6. if (node instanceof Element) {
  7. Element ele = (Element) node;
  8. if (delegate.isDefaultNamespace(ele)) {
  9. parseDefaultElement(ele, delegate);
  10. }
  11. else {
  12. delegate.parseCustomElement(ele);
  13. }
  14. }
  15. }
  16. }
  17. else {
  18. delegate.parseCustomElement(root);
  19. }
  20. }
  1. 若是默认元素标签:bean、import、alias等,走parseDefaultElement(ele, delegate);

    1. private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    2. if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
    3. //import标签
    4. importBeanDefinitionResource(ele);
    5. }
    6. else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
    7. //alias标签
    8. processAliasRegistration(ele);
    9. }
    10. else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
    11. //bean标签
    12. processBeanDefinition(ele, delegate);
    13. }
    14. else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
    15. // recurse
    16. doRegisterBeanDefinitions(ele);
    17. }
    18. }
  2. 若是自定义标签:走delegate.parseCustomElement(ele);

Bean标签的解析

方法:DefaultBeanDefinitionDocumentReader#processBeanDefinition

image.png

  1. 委托BeanDefinitionDelegate类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHodler
  2. 若默认标签的子标签下有自定义标签,会执行BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired()方法
  3. BeanDefinition注册,通过BeanDefinitionReaderUtils
  4. 发送通知

    步骤1解析为BeanDefinitionHodler

  5. 判断beanName和name属性

  6. 生成GenericBeanDefinition
  7. 若无beanName,自动生成
  1. @Nullable
  2. public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
  3. //提取 id 和 name属性
  4. String id = ele.getAttribute(ID_ATTRIBUTE);
  5. String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
  6. //所有的name属性通过分词作为别名
  7. List<String> aliases = new ArrayList<>();
  8. if (StringUtils.hasLength(nameAttr)) {
  9. String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
  10. aliases.addAll(Arrays.asList(nameArr));
  11. }
  12. String beanName = id;
  13. //若未指定id则使用 name的 第一个元素作为 beanName
  14. if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
  15. beanName = aliases.remove(0);
  16. if (logger.isTraceEnabled()) {
  17. logger.trace("No XML 'id' specified - using '" + beanName +
  18. "' as bean name and " + aliases + " as aliases");
  19. }
  20. }
  21. //检查所有的别名和beanName的唯一性
  22. if (containingBean == null) {
  23. checkNameUniqueness(beanName, aliases, ele);
  24. }
  25. //将元素解析未 BeanDefiniton
  26. AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
  27. if (beanDefinition != null) {
  28. if (!StringUtils.hasText(beanName)) {
  29. try {
  30. if (containingBean != null) {
  31. beanName = BeanDefinitionReaderUtils.generateBeanName(
  32. beanDefinition, this.readerContext.getRegistry(), true);
  33. }
  34. else {
  35. beanName = this.readerContext.generateBeanName(beanDefinition);
  36. // Register an alias for the plain bean class name, if still possible,
  37. // if the generator returned the class name plus a suffix.
  38. // This is expected for Spring 1.2/2.0 backwards compatibility.
  39. String beanClassName = beanDefinition.getBeanClassName();
  40. if (beanClassName != null &&
  41. beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
  42. !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
  43. aliases.add(beanClassName);
  44. }
  45. }
  46. if (logger.isTraceEnabled()) {
  47. logger.trace("Neither XML 'id' nor 'name' specified - " +
  48. "using generated bean name [" + beanName + "]");
  49. }
  50. }
  51. catch (Exception ex) {
  52. error(ex.getMessage(), ele);
  53. return null;
  54. }
  55. }
  56. String[] aliasesArray = StringUtils.toStringArray(aliases);
  57. return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
  58. }
  59. return null;
  60. }

根据指定字符串中任一字符串分词的工具类 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);

生成GenericBeanDefinition

  1. 解析中的calss和parent
  2. 生生成BeanDefinition
  3. 解析的各种属性
  4. 解析子元素meta

image.png

  1. 解析子元素lookup-method

image.png

  1. 解析子元素replaced-method
  2. 解析子元素constructor-arg
  3. 解析子元素property
  4. 解析子元素qualifier

    1. @Nullable
    2. public AbstractBeanDefinition parseBeanDefinitionElement(
    3. Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    4. this.parseState.push(new BeanEntry(beanName));
    5. String className = null;
    6. if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
    7. className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    8. }
    9. String parent = null;
    10. if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
    11. parent = ele.getAttribute(PARENT_ATTRIBUTE);
    12. }
    13. try {
    14. AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    15. //解析 parent scope/lazy-init等属性
    16. parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    17. bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    18. //
    19. parseMetaElements(ele, bd);
    20. //解析lookup
    21. parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    22. parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    23. //解析构造函数参数
    24. parseConstructorArgElements(ele, bd);
    25. //解析属性
    26. parsePropertyElements(ele, bd);
    27. parseQualifierElements(ele, bd);
    28. bd.setResource(this.readerContext.getResource());
    29. bd.setSource(extractSource(ele));
    30. return bd;
    31. }
    32. catch (ClassNotFoundException ex) {
    33. error("Bean class [" + className + "] not found", ele, ex);
    34. }
    35. catch (NoClassDefFoundError err) {
    36. error("Class that bean class [" + className + "] depends on not found", ele, err);
    37. }
    38. catch (Throwable ex) {
    39. error("Unexpected failure during bean definition parsing", ele, ex);
    40. }
    41. finally {
    42. this.parseState.pop();
    43. }
    44. return null;
    45. }

    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;

  1. <a name="PMzub"></a>
  2. ## 步骤2解析自定义标签
  3. <a name="WL1Fm"></a>
  4. ## 步骤3注册成为BeanDefinition
  5. 通过`BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,getReaderContext().getRegistry())`进行注册
  6. ```java
  7. public static void registerBeanDefinition(
  8. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  9. throws BeanDefinitionStoreException {
  10. // Register bean definition under primary name.
  11. String beanName = definitionHolder.getBeanName();
  12. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
  13. // Register aliases for bean name, if any. beanName的别名
  14. String[] aliases = definitionHolder.getAliases();
  15. if (aliases != null) {
  16. for (String alias : aliases) {
  17. registry.registerAlias(beanName, alias);
  18. }
  19. }
  20. }

注册beanName->BeanDefinition

  1. @Override
  2. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  3. throws BeanDefinitionStoreException {
  4. //校验
  5. if (beanDefinition instanceof AbstractBeanDefinition) {
  6. try {
  7. ((AbstractBeanDefinition) beanDefinition).validate();
  8. }
  9. catch (BeanDefinitionValidationException ex) {
  10. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  11. "Validation of bean definition failed", ex);
  12. }
  13. }
  14. //若存在,需要判断是否允许覆盖
  15. BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
  16. if (existingDefinition != null) {
  17. if (!isAllowBeanDefinitionOverriding()) {
  18. throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
  19. }
  20. else if (existingDefinition.getRole() < beanDefinition.getRole()) {
  21. // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
  22. if (logger.isInfoEnabled()) {
  23. logger.info("Overriding user-defined bean definition for bean '" + beanName +
  24. "' with a framework-generated bean definition: replacing [" +
  25. existingDefinition + "] with [" + beanDefinition + "]");
  26. }
  27. }
  28. else if (!beanDefinition.equals(existingDefinition)) {
  29. if (logger.isDebugEnabled()) {
  30. logger.debug("Overriding bean definition for bean '" + beanName +
  31. "' with a different definition: replacing [" + existingDefinition +
  32. "] with [" + beanDefinition + "]");
  33. }
  34. }
  35. else {
  36. if (logger.isTraceEnabled()) {
  37. logger.trace("Overriding bean definition for bean '" + beanName +
  38. "' with an equivalent definition: replacing [" + existingDefinition +
  39. "] with [" + beanDefinition + "]");
  40. }
  41. }
  42. this.beanDefinitionMap.put(beanName, beanDefinition);
  43. }
  44. else {
  45. //r若已经又Bean创建了
  46. if (hasBeanCreationStarted()) {
  47. // Cannot modify startup-time collection elements anymore (for stable iteration)
  48. synchronized (this.beanDefinitionMap) {
  49. this.beanDefinitionMap.put(beanName, beanDefinition);
  50. List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
  51. updatedDefinitions.addAll(this.beanDefinitionNames);
  52. updatedDefinitions.add(beanName);
  53. this.beanDefinitionNames = updatedDefinitions;
  54. removeManualSingletonName(beanName);
  55. }
  56. }
  57. else {
  58. // Still in startup registration phase
  59. this.beanDefinitionMap.put(beanName, beanDefinition);
  60. this.beanDefinitionNames.add(beanName);
  61. removeManualSingletonName(beanName);
  62. }
  63. this.frozenBeanDefinitionNames = null;
  64. }
  65. if (existingDefinition != null || containsSingleton(beanName)) {
  66. resetBeanDefinition(beanName);
  67. }
  68. else if (isConfigurationFrozen()) {
  69. clearByTypeCache();
  70. }
  71. }

注册alia->beanName

  1. @Override
  2. public void registerAlias(String name, String alias) {
  3. Assert.hasText(name, "'name' must not be empty");
  4. Assert.hasText(alias, "'alias' must not be empty");
  5. synchronized (this.aliasMap) {
  6. if (alias.equals(name)) {
  7. this.aliasMap.remove(alias);
  8. if (logger.isDebugEnabled()) {
  9. logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
  10. }
  11. }
  12. else {
  13. String registeredName = this.aliasMap.get(alias);
  14. if (registeredName != null) {
  15. if (registeredName.equals(name)) {
  16. // An existing alias - no need to re-register
  17. return;
  18. }
  19. if (!allowAliasOverriding()) {
  20. throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
  21. name + "': It is already registered for name '" + registeredName + "'.");
  22. }
  23. if (logger.isDebugEnabled()) {
  24. logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
  25. registeredName + "' with new target name '" + name + "'");
  26. }
  27. }
  28. checkForAliasCircle(name, alias);
  29. this.aliasMap.put(alias, name);
  30. if (logger.isTraceEnabled()) {
  31. logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
  32. }
  33. }
  34. }
  35. }

会检查循环的问题 A->B->A

步骤4通知注册完成