资讯专栏INFORMATION COLUMN

追踪解析Spring ioc启动源码(2)

funnyZhang / 1896人阅读

摘要:顾名思义,其主要作用是解析标签。本例中没有用到上述的注解,所以均为。继续追踪这行代码的内部实现获取的名称调用的方法注册过程见处理的别名,本例中没有别名,不进入循环的具体内容有待研究,不展开。到此为止,已经被注册到中。

接上篇 3 reader 注册配置类

该 part 的起点:

</>复制代码

  1. public AnnotationConfigApplicationContext(Class... annotatedClasses) {
  2. this();
  3. register(annotatedClasses); // 3 reader 注册配置类
  4. refresh();
  5. }

该行代码会将 iocConfig bean 注册到 reader 中
AnnotationConfigApplicationContext 的 register 方法:

</>复制代码

  1. //AnnotationConfigApplicationContext.class
  2. public void register(Class... annotatedClasses) {
  3. //参数非空效验
  4. Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
  5. //调用 AnnotatedBeanDefinitionReader 的 register 方法
  6. this.reader.register(annotatedClasses);
  7. }

上述方法主要是调用了 AnnotatedBeanDefinitionReader 的 register 方法:

</>复制代码

  1. //AnnotatedBeanDefinitionReader.class
  2. public void register(Class... annotatedClasses) {
  3. for (Class annotatedClass : annotatedClasses) {
  4. registerBean(annotatedClass);
  5. }
  6. }

上述方法循环调用了 AnnotatedBeanDefinitionReader 的 registerBean 方法:

</>复制代码

  1. //AnnotatedBeanDefinitionReader.class
  2. public void registerBean(Class annotatedClass) {
  3. doRegisterBean(annotatedClass, null, null, null);
  4. }

上述方法调用了 AnnotatedBeanDefinitionReader 的 doRegisterBean 方法,这个方法比较长,需要重点关注:

</>复制代码

  1. //AnnotatedBeanDefinitionReader.class
  2. void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
  3. @Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
  4. //用 BeanDefinition 包装 iocConfig
  5. AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
  6. //此段代码用于处理 Conditional 注解,在特定条件下阻断 bean 的注册
  7. //本例中此处不会 return
  8. //3.1
  9. if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
  10. return;
  11. }
  12. //用来创建 bean 的 supplier,会替代掉 bean 本身的创建方法
  13. //instanceSupplier 一般情况下为 null
  14. abd.setInstanceSupplier(instanceSupplier);
  15. //此行代码处理 scope 注解,本例中 scope 是默认值 singleton
  16. //3.2
  17. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
  18. abd.setScope(scopeMetadata.getScopeName());
  19. //bean name 在本例中为自动生成的 iocConfig
  20. //3.3
  21. String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
  22. //特定注解解析,本例中均不做操作
  23. //3.4
  24. AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
  25. //本例中 qualifiers 传入的是 null
  26. //3.5
  27. if (qualifiers != null) {
  28. for (Class qualifier : qualifiers) {
  29. if (Primary.class == qualifier) {
  30. abd.setPrimary(true);
  31. }
  32. else if (Lazy.class == qualifier) {
  33. abd.setLazyInit(true);
  34. }
  35. else {
  36. abd.addQualifier(new AutowireCandidateQualifier(qualifier));
  37. }
  38. }
  39. }
  40. //本例中 definitionCustomizers 传入的是 null
  41. //3.6
  42. for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
  43. customizer.customize(abd);
  44. }
  45. //用 BeanDefinitionHolder 包装 BeanDefinition
  46. BeanDefinitionHolder definitionHolder
  47. = new BeanDefinitionHolder(abd,beanName);
  48. //此行代码与动态代理和 scope 注解有关,但是在本案例中没有做任何操作,只是返回了传入的 definitionHolder
  49. //3.7
  50. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  51. //iocConfig 注册
  52. // 3.8
  53. BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
  54. }
3.1

看一下上述方法的片段:

</>复制代码

  1. if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
  2. return;
  3. }

首先需要了解到 abd 的 getMetadata() 方法会获取到 abd 中的 metadata 对象。

该对象是一个 StandardAnnotationMetadata 的实例化对象,在创建的时候会利用 java.Class 中的 api 获取 bean 中所有的注解,并保存为一个数组:

</>复制代码

  1. //StandardAnnotationMetadata.class
  2. public StandardAnnotationMetadata(Class introspectedClass, boolean nestedAnnotationsAsMap) {
  3. //此处的 introspectedClass 即为 bean 的 class
  4. //父类的构造器用于内部保存 bean 的 class
  5. super(introspectedClass);
  6. //获取所有的注解
  7. this.annotations = introspectedClass.getAnnotations();
  8. //nestedAnnotationsAsMap 暂时用不上,按下不表
  9. //nestedAnnotationsAsMap = true
  10. this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
  11. }

conditionEvaluator 是一个注解解析器,在 AnnotatedBeanDefinitionReader 创建的时候在其构造方法内被创建:

</>复制代码

  1. this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

追踪 conditionEvaluator 的 shouldSkip(...) 方法:

</>复制代码

  1. //ConditionEvaluator.class
  2. public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
  3. return shouldSkip(metadata, null); //调用自身的重载方法
  4. }
  5. //ConditionEvaluator.class
  6. public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
  7. //metadata 在此处不为 null
  8. //判断 bean 是否使用了 Conditional 注解
  9. if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
  10. //如果 metadata为空或者 bean 没有使用 Conditional 注解,就会返回 false
  11. return false;
  12. }
  13. //第一次调用该方法的时候,phase 为 null
  14. if (phase == null) {
  15. //下列源码规整一下,其实是四个条件:
  16. //1 bean.metadata 是 AnnotationMetadata 或其子类
  17. //2 bean 使用了 Configuration 注解
  18. //3 bean 不是一个接口
  19. //4 bean 使用了 Component、ComponentScan、Import、ImportResource 这四个注解之一,或者使用了 Bean 注解
  20. //这四个条件中满足 12 或者 134 就会进入 if 语句中
  21. //请注意,对于 config bean 来说,只要使用了 Conditional 注解,必然会进入到语句中
  22. if (metadata instanceof AnnotationMetadata &&
  23. ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
  24. return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
  25. }
  26. return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
  27. }
  28. List conditions = new ArrayList<>();
  29. //getConditionClasses(metadata) 会获取到 Conditional 注解中的 value 数组
  30. for (String[] conditionClasses : getConditionClasses(metadata)) {
  31. //遍历数组
  32. for (String conditionClass : conditionClasses) {
  33. //利用反射获取实例化数组内的 class
  34. Condition condition = getCondition(conditionClass, this.context.getClassLoader());
  35. conditions.add(condition); //获取所有的 canditionClass 并以次存入到列表中
  36. }
  37. }
  38. //利用了 List 自带的排序 api 进行排序
  39. AnnotationAwareOrderComparator.sort(conditions);
  40. for (Condition condition : conditions) {
  41. ConfigurationPhase requiredPhase = null;
  42. if (condition instanceof ConfigurationCondition) {
  43. requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
  44. }
  45. //对于 Conditional 内的 value 并非是实现 ConfigurationCondition 接口的 class,requiredPhase == null 必然为 true;对于实现了该接口的 class,requiredPhase == phase 必然为 true
  46. //所以要注意,如果 value classmatches(...) 方法返回 false,则会在此处阻断 bean 的注册
  47. if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
  48. return true;
  49. }
  50. }
  51. //正常情况下,做完所有检查工作之后还是会返回 false
  52. return false;
  53. }

可以看到这个方法其实是 Conditional 注解的解析器,对于未使用这个注解的 bean,直接就返回了,不会继续往下走。

先来看一下 Conditional 的源码:

</>复制代码

  1. @Target({ElementType.TYPE, ElementType.METHOD}) //可以标注在类和方法上方
  2. @Retention(RetentionPolicy.RUNTIME) //注解生命周期
  3. @Documented //javadoc 相关
  4. public @interface Conditional {
  5. //class 数组
  6. //这个数组里的值必须要是实现了 Condition 接口的类
  7. //注意这个 value 没有默认值,如果要使用该注解就必须要填入
  8. Class[] value();
  9. }

顺便来看一下 Condition 接口:

</>复制代码

  1. public interface Condition {
  2. //这个方法会返回一个 boolean 值,如果为 true,则将继承该接口的类注入到 Conditional 修饰的 bean 中
  3. boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
  4. }

conditional 的具体内容有待研究,不展开。

3.2

看下方代码片段:

</>复制代码

  1. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
  2. abd.setScope(scopeMetadata.getScopeName());

scopeMetadataResolver 是一个定义在 AnnotatedBeanDefinitionReader 里的 AnnotationScopeMetadataResolver 对象。顾名思义,其主要作用是解析 scope 标签。

先来看一下 Scope 注解的定义源码:

</>复制代码

  1. @Target({ElementType.TYPE, ElementType.METHOD}) //可以标注在类和方法上方
  2. @Retention(RetentionPolicy.RUNTIME) //注解生命周期
  3. @Documented //javadoc 相关
  4. public @interface Scope {
  5. //value 是平时开发中最常用到的 scope 属性,用来设置是否是单例模式
  6. //在处理注解的时候 value 属性会被转化成 scopeName 属性来看待
  7. //所以两个属性其实是一样的
  8. String value() default "";
  9. String scopeName() default "";
  10. //代理模式设置,默认为无代理
  11. ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
  12. }

ScopedProxyMode 是一个枚举类,没有任何处理业务逻辑的代码,一同放在这里:

</>复制代码

  1. public enum ScopedProxyMode {
  2. DEFAULT, //不使用代理,defaultno 是等价的
  3. NO,
  4. INTERFACES, //使用 jdk 自带的动态代理 api 进行创建
  5. TARGET_CLASS; //target-class 模式,需要使用 cglib 进行 bean 的创建
  6. }

AnnotationScopeMetadataResolver 的 resolveScopeMetadata(...) 方法具体实现如下:

</>复制代码

  1. //AnnotationScopeMetadataResolver.class
  2. public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
  3. //创建一个 metadata 对象用于返回
  4. ScopeMetadata metadata = new ScopeMetadata();
  5. if (definition instanceof AnnotatedBeanDefinition) {
  6. AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
  7. //从 bean 的注解里寻找 scope 这个注解
  8. AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
  9. annDef.getMetadata(), this.scopeAnnotationType);
  10. //如果 bean 确实是用了 scope 注解
  11. if (attributes != null) {
  12. metadata.setScopeName(attributes.getString("value")); //存入 scope 的 value 属性值
  13. //获取 proxyMode 属性值
  14. ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
  15. //defaultno 是等同的,默认会转化成 no 进行处理
  16. if (proxyMode == ScopedProxyMode.DEFAULT) {
  17. //this.defaultProxyMode = ScopedProxyMode.NO
  18. proxyMode = this.defaultProxyMode;
  19. }
  20. metadata.setScopedProxyMode(proxyMode); //存入 scope 的 proxyMode 属性值
  21. }
  22. }
  23. //没有使用 scope 的情况下会返回一个新建的 metadata
  24. return metadata;
  25. }

annDef.getMetadata() 会获取到一个 AnnotationMetadata 对象,里面包含了 bean 的所有注解信息。

scopeAnnotationType 是一个定义在 AnnotationScopeMetadataResolver 里的 Class 对象:

</>复制代码

  1. protected Class scopeAnnotationType = Scope.class;

可见 AnnotationConfigUtils 的 attributesFor(...) 就是去注解集里查找 scope 注解,并且封装成一个 AnnotationAttributes 返回。
AnnotationAttributes 是 Spring 用来存储注解所定义的一种数据结构,本质上是一个 LinkedHashMap。

再回到本小节最上方的代码:

</>复制代码

  1. abd.setScope(scopeMetadata.getScopeName());

最后其实 BeanDefinition 只接收了 scopeName,而没有接收 proxyMode。proxyMode 属性会在后面代码中用到。

3.3

看下方代码片段:

</>复制代码

  1. String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

beanNameGenerator 是一个定义在 AnnotatedBeanDefinitionReader 里的 AnnotationBeanNameGenerator 对象,顾名思义用来生成 bean 的名称:

</>复制代码

  1. private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();

追踪一下 generateBeanName(...) 方法:

</>复制代码

  1. //AnnotationBeanNameGenerator.class
  2. public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
  3. if (definition instanceof AnnotatedBeanDefinition) {
  4. //determineBeanNameFromAnnotation(...) 方法会从 bean 的所有注解里去遍历搜寻 bean 名称
  5. String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
  6. //如果此处的 beanName 非空,则表明在注解里找到了定义的 bean 名称
  7. if (StringUtils.hasText(beanName)) {
  8. // Explicit bean name found.
  9. return beanName;
  10. }
  11. }
  12. //没有在前面 return,证明 bean 没有被设置名称,则在此处默认生成一个名称
  13. return buildDefaultBeanName(definition, registry);
  14. }

看一眼 buildDefaultBeanName(...) 方法:

</>复制代码

  1. //AnnotationBeanNameGenerator.class
  2. protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
  3. return buildDefaultBeanName(definition);
  4. }

其实这个方法只用到了 definition,而没有使用到传入的 registry。

继续追踪代码实现:

</>复制代码

  1. //AnnotationBeanNameGenerator.class
  2. protected String buildDefaultBeanName(BeanDefinition definition) {
  3. //该处返回的是 bean 的整个 class 路径和名称
  4. String beanClassName = definition.getBeanClassName();
  5. //beanClassName 非空判断
  6. Assert.state(beanClassName != null, "No bean class name set");
  7. //截掉 class 的路径,只取 class 名称
  8. String shortClassName = ClassUtils.getShortName(beanClassName);
  9. //将首字母小写并返回
  10. return Introspector.decapitalize(shortClassName);
  11. }
3.4

看下方代码实现:

</>复制代码

  1. AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

追踪这行代码:

</>复制代码

  1. //AnnotationConfigUtils.class
  2. public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
  3. //调用重载方法
  4. processCommonDefinitionAnnotations(abd, abd.getMetadata());
  5. }
  6. //AnnotationConfigUtils.class
  7. static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
  8. //检查 lazy 注解
  9. AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
  10. if (lazy != null) {
  11. abd.setLazyInit(lazy.getBoolean("value"));
  12. }else if (abd.getMetadata() != metadata) {
  13. //这里还有一个补充检查,如果传入的 metadata 不是 abd 内部的 metadata的话,还会继续进来判断一次
  14. //在本例中没什么必要
  15. lazy = attributesFor(abd.getMetadata(), Lazy.class);
  16. if (lazy != null) {
  17. abd.setLazyInit(lazy.getBoolean("value"));
  18. }
  19. }
  20. //检查 primary 注解
  21. if (metadata.isAnnotated(Primary.class.getName())) {
  22. abd.setPrimary(true);
  23. }
  24. //检查 dependsOn 注解
  25. AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
  26. if (dependsOn != null) {
  27. abd.setDependsOn(dependsOn.getStringArray("value"));
  28. }
  29. //检查 role 注解
  30. AnnotationAttributes role = attributesFor(metadata, Role.class);
  31. if (role != null) {
  32. abd.setRole(role.getNumber("value").intValue());
  33. }
  34. //检查 description 注解
  35. AnnotationAttributes description = attributesFor(metadata, Description.class);
  36. if (description != null) {
  37. abd.setDescription(description.getString("value"));
  38. }
  39. }

其实上述代码的主体都是类似的,步骤都是尝试从 metadata 中获取特定注解,如果获取到了就将其作为一个属性值 set 进 abd 中。

这里需要强调 abd 就是要注册的 bean 的 BeanDefinition 包装对象。

本例中没有用到上述的注解,所以均为 null。

3.5

看下方代码:

</>复制代码

  1. if (qualifiers != null) {
  2. //在 qualifiers 不为 null 的情况下会遍历该集合,并将当中的所有的元素解析出来,进行业务操作
  3. for (Class qualifier : qualifiers) {
  4. if (Primary.class == qualifier) {
  5. abd.setPrimary(true);
  6. }else if (Lazy.class == qualifier) {
  7. abd.setLazyInit(true);
  8. }else {
  9. abd.addQualifier(new AutowireCandidateQualifier(qualifier));
  10. }
  11. }
  12. }

上述代码是针对 qualifier 注解的解析,和 3.4 很类似。

AutowireCandidateQualifier 是注解的包装类,储存了一个特定注解的名字和 value。abd 的 addQualifier(...) 方法会将这个创建出来的包装类存储到一个 map 对象里。

3.6

看下方代码:

</>复制代码

  1. for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
  2. customizer.customize(abd);
  3. }

这段代码是 Spring5 中新加入的。根据注释,官方应该是留下这个接口用以让开发者通过 lambda 表达式去定义 bean。

3.7

看下方代码:

</>复制代码

  1. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

先来追踪 applyScopedProxyMode(...) 方法:

</>复制代码

  1. //AnnotationConfigUtils.class
  2. static BeanDefinitionHolder applyScopedProxyMode(
  3. ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
  4. //先判断 scope 注解的使用
  5. ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
  6. if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
  7. return definition;
  8. }
  9. //判断具体使用哪种模式
  10. boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
  11. //此行代码会连向 spring-aop 包下的类来处理
  12. return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
  13. }

注意,此处传入的 metadata 是上述 3.2 小节中新建出来并返回的对象:

</>复制代码

  1. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);

对于一般没有使用 scope 注解或者 scope 注解为默认的 bean,此时 scopedProxyMode 是等于 ScopedProxyMode.NO 的。

对于 scopedProxyMode 不为 NO 的 bean,均为需要使用动态代理进行创建的对象,区别只是使用 jdk 自带的 api 还是使用 cglib 包。

追踪一下 ScopedProxyCreator 的 createScopedProxy(...) 方法:

</>复制代码

  1. //ScopedProxyCreator.class
  2. public static BeanDefinitionHolder createScopedProxy(
  3. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
  4. return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
  5. }

继续追踪:

</>复制代码

  1. //ScopedProxyUtils.class
  2. public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
  3. BeanDefinitionRegistry registry, boolean proxyTargetClass) {
  4. //bean 的名称
  5. String originalBeanName = definition.getBeanName();
  6. //bean 的 BeanDefinition 包装类
  7. BeanDefinition targetDefinition = definition.getBeanDefinition();
  8. //在 bean 的名称前面加上字符串 "scopedTarget." ,拼成 targetBeanName
  9. //比如 scopedTarget.iocConfig
  10. String targetBeanName = getTargetBeanName(originalBeanName);
  11. //以下代码用来组装一个动态代理的工厂 bean,这个 bean 是用来动态代理的主体
  12. RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
  13. proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
  14. proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
  15. proxyDefinition.setSource(definition.getSource());
  16. proxyDefinition.setRole(targetDefinition.getRole());
  17. proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
  18. if (proxyTargetClass) {
  19. targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
  20. }else {
  21. proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
  22. }
  23. proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
  24. proxyDefinition.setPrimary(targetDefinition.isPrimary());
  25. if (targetDefinition instanceof AbstractBeanDefinition) {
  26. proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
  27. }
  28. targetDefinition.setAutowireCandidate(false);
  29. targetDefinition.setPrimary(false);
  30. //此处的 targetDefinition 是传入的 bean 的包装类
  31. //这一步会提前将该 bean 进行注册
  32. //注册过程见 2.2
  33. registry.registerBeanDefinition(targetBeanName, targetDefinition);
  34. //返回的其实是动态代理所需要的工厂 bean
  35. return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
  36. }

scope 的具体内容有待研究,不展开。

3.8

在上例代码中的这一行中:

</>复制代码

  1. BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

传入的 definitionHolder 就是 iocConfig bean 的包装对象;而传入的 registry 就是在 ApplicationContext 中实例化的 BeanFactory,此处具体而言就是DefaultListableBeanFactory。

继续追踪这行代码的内部实现:

</>复制代码

  1. //BeanDefinitionReaderUtils.class
  2. public static void registerBeanDefinition(
  3. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  4. throws BeanDefinitionStoreException {
  5. //获取bean的名称
  6. String beanName = definitionHolder.getBeanName();
  7. //调用 AnnotationConfigApplicationContext 的 registerBeanDefinition 方法
  8. //注册过程见 2.2
  9. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
  10. //处理bean的别名,本例中没有别名,不进入循环
  11. String[] aliases = definitionHolder.getAliases();
  12. if (aliases != null) {
  13. for (String alias : aliases) {
  14. registry.registerAlias(beanName, alias);
  15. }
  16. }
  17. }

alias 的具体内容有待研究,不展开。

到此为止,iocConfig bean 已经被注册到 bean factory 中。

To Be Continued ...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72747.html

相关文章

  • 追踪解析Spring ioc启动源码(1)

    摘要:主要过程为调用自身的另一个有参构造器此处的即为本身此处的最终返回一个调用无参构造器创建出来的对象参数非空效验保存创建一个用于注解解析器,后面会用到注册需要用到的顾名思义,即为所处的环境,包括配置的读取等。 零 前期准备 0 FBI WARNING 文章异常啰嗦且绕弯。 1 版本 spring版本 : spring 5.1.2.RELEASE IDE : idea 2018.3 2 Be...

    Cheng_Gang 评论0 收藏0
  • 重拾-Spring-IOC

    摘要:为何重拾使用了多年,但是对其底层的一些实现还是一知半解,一些概念比较模糊故决定重新拾起,加深对的认识。小结是在完成创建后对其进行后置处理的接口是在完成实例化对其进行的后置处理接口是框架底层的核心接口,其提供了创建,获取等核心功能。 为何重拾 使用了 Spring 多年,但是对其底层的一些实现还是一知半解,一些概念比较模糊;故决定重新拾起,加深对 Spring 的认识。 重拾计划 spr...

    GraphQuery 评论0 收藏0
  • Spring AOP从零单排-织入时期源码分析

    摘要:何为简单点来定义就是切面,是一种编程范式。定义一个切面的载体定义一个切点定义一个为,并指定对应的切点一个注册配置类,启动容器,初始化时期获取对象,获取对象时期,并进行打印好了,这样我们整体的代理就已经完成。 问题:Spring AOP代理中的运行时期,是在初始化时期织入还是获取对象时期织入? 织入就是代理的过程,指目标对象进行封装转换成代理,实现了代理,就可以运用各种代理的场景模式。 ...

    honmaple 评论0 收藏0
  • Spring专题之IOC源码分析

    摘要:前言以下源码基于版本解析。实现源码分析对于的实现,总结来说就是定位加载和注册。定位就是需要定位配置文件的位置,加载就是将配置文件加载进内存注册就是通过解析配置文件注册。下面我们从其中的一种使用的方式一步一步的分析的实现源码。 前言 以下源码基于Spring 5.0.2版本解析。 什么是IOC容器? 容器,顾名思义可以用来容纳一切事物。我们平常所说的Spring IOC容器就是一个可以容...

    不知名网友 评论0 收藏0
  • SpringBoot 中 @SpringBootApplication注解背后的三体结构探秘

    摘要:概述约定大于配置的功力让我们如沐春风,在我之前写的文章从到也对比过和这两个框架,不过最终以超高的代码信噪比和易上手性让我们映像颇深。至于,我想在非时代大家应该不陌生吧,作用是配置容器,也即形式的容器的配置类所使用。 showImg(https://segmentfault.com/img/remote/1460000015822144); 概 述 SpringBoot 约定大于配置...

    Tecode 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<