查看原文
其他

Spring源码(三)-Context的创建核心逻辑(下)

孙亮亮 SpringForAll社区 2021-05-26


由于该篇文章较多,所以就拆分为了上下两篇,接上面完成了beanFactory的信息处理,接下来是bean的相关定义的处理。

1、BEANDEFINITION

获取完beanFactory的之后,代码涉及到了一些bean的定义,接下来看beanDefination的定义。

1、BeanDefinition 设计bean相关信息

2、BeanDefinitionHolder 封装bean定义相关信息,以及bean名称、别名等

3、BeanDefinitionRegistry 持有所有注册的bean相关信息

下面我们接着上面一篇 registerAnnotationConfigProcessors()方法的分析。

  1. if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {

  2. RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

  3. def.setSource(source);

  4. beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

  5. }

这段代码以及其紧跟的代码为创建若干bean,其中

  1. registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)

表示注册名称为 org.springframework.context.annotation.internalConfigurationAnnotationProcessorbeanClass对应为ConfigurationClassPostProcessorbean

2、BEAN注册

  1. private static BeanDefinitionHolder registerPostProcessor(

  2. BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {


  3. definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

  4. registry.registerBeanDefinition(beanName, definition);

  5. return new BeanDefinitionHolder(definition, beanName);

  6. }

其中 registry.registerBeanDefinition(beanName,definition)调用GenericApplicationContext中的方法

  1. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

  2. throws BeanDefinitionStoreException {


  3. this.beanFactory.registerBeanDefinition(beanName, beanDefinition);

  4. }

其中this.beanFactory为DefaultListableBeanFactory实例

  1. @Override

  2. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

  3. throws BeanDefinitionStoreException {


  4. Assert.hasText(beanName, "Bean name must not be empty");

  5. Assert.notNull(beanDefinition, "BeanDefinition must not be null");


  6. if (beanDefinition instanceof AbstractBeanDefinition) {

  7. try {

  8. ((AbstractBeanDefinition) beanDefinition).validate();

  9. }

  10. catch (BeanDefinitionValidationException ex) {

  11. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,

  12. "Validation of bean definition failed", ex);

  13. }

  14. }


  15. BeanDefinition oldBeanDefinition;


  16. oldBeanDefinition = this.beanDefinitionMap.get(beanName);

  17. if (oldBeanDefinition != null) {

  18. if (!isAllowBeanDefinitionOverriding()) {

  19. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,

  20. "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +

  21. "': There is already [" + oldBeanDefinition + "] bound.");

  22. }

  23. else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {

  24. // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE

  25. if (this.logger.isWarnEnabled()) {

  26. this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +

  27. "' with a framework-generated bean definition: replacing [" +

  28. oldBeanDefinition + "] with [" + beanDefinition + "]");

  29. }

  30. }

  31. else if (!beanDefinition.equals(oldBeanDefinition)) {

  32. if (this.logger.isInfoEnabled()) {

  33. this.logger.info("Overriding bean definition for bean '" + beanName +

  34. "' with a different definition: replacing [" + oldBeanDefinition +

  35. "] with [" + beanDefinition + "]");

  36. }

  37. }

  38. else {

  39. if (this.logger.isDebugEnabled()) {

  40. this.logger.debug("Overriding bean definition for bean '" + beanName +

  41. "' with an equivalent definition: replacing [" + oldBeanDefinition +

  42. "] with [" + beanDefinition + "]");

  43. }

  44. }

  45. this.beanDefinitionMap.put(beanName, beanDefinition);

  46. }

  47. else {

  48. if (hasBeanCreationStarted()) {

  49. // Cannot modify startup-time collection elements anymore (for stable iteration)

  50. synchronized (this.beanDefinitionMap) {

  51. this.beanDefinitionMap.put(beanName, beanDefinition);

  52. List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);

  53. updatedDefinitions.addAll(this.beanDefinitionNames);

  54. updatedDefinitions.add(beanName);

  55. this.beanDefinitionNames = updatedDefinitions;

  56. if (this.manualSingletonNames.contains(beanName)) {

  57. Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);

  58. updatedSingletons.remove(beanName);

  59. this.manualSingletonNames = updatedSingletons;

  60. }

  61. }

  62. }

  63. else {

  64. // Still in startup registration phase

  65. this.beanDefinitionMap.put(beanName, beanDefinition);

  66. this.beanDefinitionNames.add(beanName);

  67. this.manualSingletonNames.remove(beanName);

  68. }

  69. this.frozenBeanDefinitionNames = null;

  70. }


  71. if (oldBeanDefinition != null || containsSingleton(beanName)) {

  72. resetBeanDefinition(beanName);

  73. }

  74. }

以上方法完成了bean的注册;1、首先完成校验

  1. ((AbstractBeanDefinition) beanDefinition).validate()

2、接下来从map中获取bean,首次获取肯定是空

  1. oldBeanDefinition = this.beanDefinitionMap.get(beanName);

3、为空进入以下代码

  1. if (hasBeanCreationStarted()) {

  2. // Cannot modify startup-time collection elements anymore (for stable iteration)

  3. synchronized (this.beanDefinitionMap) {

  4. this.beanDefinitionMap.put(beanName, beanDefinition);

  5. List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);

  6. updatedDefinitions.addAll(this.beanDefinitionNames);

  7. updatedDefinitions.add(beanName);

  8. this.beanDefinitionNames = updatedDefinitions;

  9. if (this.manualSingletonNames.contains(beanName)) {

  10. Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);

  11. updatedSingletons.remove(beanName);

  12. this.manualSingletonNames = updatedSingletons;

  13. }

  14. }

  15. }

  16. else {

  17. // Still in startup registration phase

  18. this.beanDefinitionMap.put(beanName, beanDefinition);

  19. this.beanDefinitionNames.add(beanName);

  20. this.manualSingletonNames.remove(beanName);

  21. }

  22. this.frozenBeanDefinitionNames = null;

这里顺便解释下,在从map中获取到bean时表示bean已经注册,则会判断是否可以覆盖oldBean,也需要判断bean对应的Role级别

以上完成了AnnotationConfigEmbeddedWebApplicationContext中 AnnotatedBeanDefinitionReader实例的构造

接下来为ClassPathBeanDefinitionScanner实例的创建

  1. public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {

  2. this(registry, useDefaultFilters, getOrCreateEnvironment(registry));

  3. }

调用内部方法

  1. public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,

  2. Environment environment, @Nullable ResourceLoader resourceLoader) {


  3. Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

  4. this.registry = registry;


  5. if (useDefaultFilters) {

  6. //注册默认拦截器,将Component、ManagedBean、Named注解增加到包含过滤规则中。

  7. registerDefaultFilters();

  8. }

  9. setEnvironment(environment);

  10. //完成对resourcePatternResolver以及metadataReaderFactory的赋值操作。

  11. setResourceLoader(resourceLoader);

  12. }

调用super构造

  1. public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {

  2. if (useDefaultFilters) {

  3. registerDefaultFilters();

  4. }

  5. Assert.notNull(environment, "Environment must not be null");

  6. this.environment = environment;

  7. }

在该方法中完成了environment的赋值以及为ClassPathScanningCandidateComponentProvider完成了默认过滤器的注册

  1. protected void registerDefaultFilters() {

  2. this.includeFilters.add(new AnnotationTypeFilter(Component.class));

  3. ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();

  4. try {

  5. this.includeFilters.add(new AnnotationTypeFilter(

  6. ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));

  7. logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");

  8. }

  9. catch (ClassNotFoundException ex) {

  10. // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.

  11. }

  12. try {

  13. this.includeFilters.add(new AnnotationTypeFilter(

  14. ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));

  15. logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");

  16. }

  17. catch (ClassNotFoundException ex) {

  18. // JSR-330 API not available - simply skip.

  19. }

  20. }

将Component、ManagedBean、Named注解增加到包含过滤规则中。

  1. setResourceLoader((ResourceLoader) this.registry)

  2. public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {

  3. this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);

  4. this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);

  5. this.componentsIndex = CandidateComponentsIndexLoader.loadIndex(this.resourcePatternResolver.getClassLoader());

  6. }

完成对resourcePatternResolver以及metadataReaderFactory的赋值操作。至此,完成了对上下文的创建

代码的构建请参考 github该地址有相应代码的注释

Spring源码分析


推荐:人人都是 API 设计者:我对 RESTful API、GraphQL、RPC API 的思考

上一篇:Springboot与Elasticsearch完美结合

点击原文阅读更多



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存