栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring底层原理(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring底层原理(一)

一、Spring的使用

使用Spring的代码:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
userService.test();

第一行代码,会构造一个ClassPathXmlApplicationContext对象,ClassPathXmlApplicationContext该如何理解,调用该构造方法除开会实例化得到一个对象,还会做哪些事情?
第二行代码,会调用ClassPathXmlApplicationContext的getBean方法,会得到一个UserService对象,getBean()是如何实现的?返回的UserService对象和我们自己直接new的UserService对象有区别吗?
第三行代码,就是简单的调用UserService的test()方法。

但是用ClassPathXmlApplicationContext其实已经过时了,在新版的Spring MVC和Spring Boot的底层主要用的都是AnnotationConfigApplicationContext,比如:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
userService.test();

可以看到AnnotationConfigApplicationContext的用法和ClassPathXmlApplicationContext是非常类似的,只不过需要传入的是一个class,而不是一个xml文件。

Spring MVC创建的是XmlWebApplicationContext,和ClassPathXmlApplicationContext类似,都是基于XML配置的
Spring Boot创建的是AnnotationConfigApplicationContext

二、Spring中是如何创建一个对象?

其实不管是AnnotationConfigApplicationContext还是ClassPathXmlApplicationContext,目前,我们都可以简单的将它们理解为就是用来创建Java对象的,比如调用getBean()就会去创建对象

在Java语言中,肯定是根据某个类来创建一个对象的。我们在看一下实例代码:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();

当我们调用context.getBean(“userService”)时,就会去创建一个对象,但是getBean方法内部怎么知道"userService"对应的是UserService类呢?

三、Bean的创建过程

一.Bean的生命周期
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
执行的时候首先会进行扫描、其次创建非懒加载的单例bean

初始化容器AnnotationConfigApplicationContext :

  public AnnotationConfigApplicationContext(Class... componentClasses) {
    this();
    this.register(componentClasses);
    this.refresh();
  }

进入到this()可以看到

 public AnnotationConfigApplicationContext() {
    StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
    this.reader = new AnnotatedBeanDefinitionReader(this);
    createAnnotatedBeanDefReader.end();
    this.scanner = new ClassPathBeanDefinitionScanner(this);//扫描器
  }

StartupStep 是spring5.3之后新增的,功能相当于飞机的黑匣子,去记录运行代码锁消耗的时间,后续源码直接跳过。

再继续到refresh()方法里面的invokeBeanFactoryPostProcessors方法去实例化bdf(BeanDefinition)Map中的单例bean

1.扫描
首先进入到扫描器(ClassPathBeanDefinitionScanner)的scan方法

public int scan(String... basePackages) {
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    this.doScan(basePackages);
    if (this.includeAnnotationConfig) {
      AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
  }

这里用的bean注册器是BeandefinitionRegister,我们只需要扫描的功能。
重点是这个方法的doScan()方法继续进入

  protected Set doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set beanDefinitions = new LinkedHashSet();
    String[] var3 = basePackages;
    int var4 = basePackages.length;
    //遍历扫描的包名,
    for(int var5 = 0; var5 < var4; ++var5) {
      String basePackage = var3[var5];
      //核心方法findCandidateComponents
      Set candidates = this.findCandidateComponents(basePackage);
      Iterator var8 = candidates.iterator();

      while(var8.hasNext()) {
        BeanDefinition candidate = (BeanDefinition)var8.next();
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
        candidate.setScope(scopeMetadata.getScopeName());
        String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
        if (candidate instanceof AbstractBeanDefinition) {
          this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
        }

        if (candidate instanceof AnnotatedBeanDefinition) {
          AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
        }

        if (this.checkCandidate(beanName, candidate)) {
          BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
          definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
          beanDefinitions.add(definitionHolder);
          this.registerBeanDefinition(definitionHolder, this.registry);
        }
      }
    }

    return beanDefinitions;
  }

方法findCandidateComponents的原理是拿到扫描到的包路径,然后获取包路径下的单例Bean然后返回,我们进入到该方法

public Set findCandidateComponents(String basePackage) {
    return this.componentsIndex != null && this.indexSupportsIncludeFilters() ? this.addCandidateComponentsFromIndex(this.componentsIndex, basePackage) : this.scanCandidateComponents(basePackage);
  }

这里用三元运算符,相当于一个if else,大部分情况下我们的spring工程都是走了else所以这里的核心方法是scanCandidateComponents(),我们继续点进去看(这里的if条件是去META-INE下找索引文件中是否有写索引文件,有的话直接去解析索引文件)

  private Set scanCandidateComponents(String basePackage) {
  //这个LinkHashSet是最后返回的结果,所以这个方法就是往这里面添加元素
    LinkedHashSet candidates = new LinkedHashSet();

    try {
      String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
      boolean traceEnabled = this.logger.isTraceEnabled();
      boolean debugEnabled = this.logger.isDebugEnabled();
      Resource[] var7 = resources;
      int var8 = resources.length;

      for(int var9 = 0; var9 < var8; ++var9) {
        Resource resource = var7[var9];
        if (traceEnabled) {
          this.logger.trace("Scanning " + resource);
        }

        try {
          MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
          if (this.isCandidateComponent(metadataReader)) {
            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
            sbd.setSource(resource);
            if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
              if (debugEnabled) {
                this.logger.debug("Identified candidate component class: " + resource);
              }

              candidates.add(sbd);
            } else if (debugEnabled) {
              this.logger.debug("Ignored because not a concrete top-level class: " + resource);
            }
          } else if (traceEnabled) {
            this.logger.trace("Ignored because not matching any filter: " + resource);
          }
        } catch (FileNotFoundException var13) {
          if (traceEnabled) {
            this.logger.trace("Ignored non-readable " + resource + ": " + var13.getMessage());
          }
        } catch (Throwable var14) {
          throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var14);
        }
      }

      return candidates;
    } catch (IOException var15) {
      throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var15);
    }
  }

上述方法里面

  1. String packageSearchPath = “classpath*:” + this.resolveBasePackage(basePackage) + ‘/’ + this.resourcePattern
    这里是拼接完整的类路径(this.resourcePattern = “**/*.class”;
  2. Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);这里是拿到一个class的文件资源(类似于file对象)
  3. ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
  public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
    Assert.notNull(metadataReader, "MetadataReader must not be null");
    this.metadata = metadataReader.getAnnotationMetadata();
    this.setBeanClassName(this.metadata.getClassName());.//只是赋值名字,并没有加载类
    this.setResource(metadataReader.getResource());
  }
  1. 遍历资源,用元信息读取器metadataReader获取类元信息(类、资源、注解),判断是否为一个bean,符合条件的加入到Set里面
    因为上述方法可以看出只有一处地方
   if (this.isCandidateComponent(metadataReader)) {
            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
            sbd.setSource(resource);
            if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
              if (debugEnabled) {
                this.logger.debug("Identified candidate component class: " + resource);
              }

              candidates.add(sbd);
            } else if (debugEnabled) {
              this.logger.debug("Ignored because not a concrete top-level class: " + resource);
            }
          }

里面有两次的isCandidateComponent方法

第一次的isCandidateComponent:

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    Iterator var2 = this.excludeFilters.iterator();

    TypeFilter tf;
    do {
      if (!var2.hasNext()) {
        var2 = this.includeFilters.iterator();

        do {
          if (!var2.hasNext()) {
            return false;
          }

          tf = (TypeFilter)var2.next();
        } while(!tf.match(metadataReader, this.getMetadataReaderFactory()));

        return this.isConditionMatch(metadataReader);
      }

      tf = (TypeFilter)var2.next();
    } while(!tf.match(metadataReader, this.getMetadataReaderFactory()));

    return false;
  }

是将带有excludeFilters 和includeFilters进行筛选,spring默认会去注册一个includeFilters的component,然后再到isConditionMatch里面有一个shouldSkip方法(就是直接判断是否有Conditional注解(我们先忽略),没有就跳过)

第二次的isCandidateComponent:

public Set findCandidateComponents(String basePackage) {
    return this.componentsIndex != null && this.indexSupportsIncludeFilters() ? this.addCandidateComponentsFromIndex(this.componentsIndex, basePackage) : this.scanCandidateComponents(basePackage);
  }

返回true的条件
1.isIndependent(顶级类or静态内部类=true)
2.isConcrete(接口=true)
3.isAbstract()&&hasAnnotatedMethods(Lookup.class.getName())(抽象类+存在lookup注解修饰的方法)
例如再java的class中

public static classA{
     class B{
     }
 }

如这样的类被spring扫描到的话也能去实例化一个对象,
因为当A类被编译的时候实际上在文件夹下会出现A.class,A$B.class两个文件

这里我们直接回到的doscan方法那边,我们拿到了candidates(装有带component且符合条件的bean类的beanDefinition)

  protected Set doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set beanDefinitions = new LinkedHashSet();
    String[] var3 = basePackages;
    int var4 = basePackages.length;
    //遍历扫描的包名,
    for(int var5 = 0; var5 < var4; ++var5) {
      String basePackage = var3[var5];
      //核心方法findCandidateComponents
      Set candidates = this.findCandidateComponents(basePackage);
      Iterator var8 = candidates.iterator();

      while(var8.hasNext()) {
        BeanDefinition candidate = (BeanDefinition)var8.next();
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);//解析单例or原型bean(注解上的scope属性默认单例)
        candidate.setScope(scopeMetadata.getScopeName());
        String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
        if (candidate instanceof AbstractBeanDefinition) {
          this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
        }

        if (candidate instanceof AnnotatedBeanDefinition) {
          AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
        }

        if (this.checkCandidate(beanName, candidate)) {
          BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
          definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
          beanDefinitions.add(definitionHolder);
          this.registerBeanDefinition(definitionHolder, this.registry);
        }
      }
    }

    return beanDefinitions;
  }

继续往下走 ScopeMetadata是去解析component注解里面的scope(单例bean还是原型bean),这里看spring去创建beanName的思路进入方法generateBeanName()

public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    if (definition instanceof AnnotatedBeanDefinition) {
      String beanName = this.determineBeanNameFromAnnotation((AnnotatedBeanDefinition)definition);
      if (StringUtils.hasText(beanName)) {
        return beanName;
      }
    }

    return this.buildDefaultBeanName(definition, registry);
  }
直接到determineBeanNameFromAnnotation()方法

 @Nullable
  protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
    AnnotationMetadata amd = annotatedDef.getMetadata();
    Set types = amd.getAnnotationTypes();
    String beanName = null;
    Iterator var5 = types.iterator();

    while(var5.hasNext()) {
      String type = (String)var5.next();
      AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
      if (attributes != null) {
        Set metaTypes = (Set)this.metaAnnotationTypesCache.computeIfAbsent(type, (key) -> {
          Set result = amd.getMetaAnnotationTypes(key);
          return result.isEmpty() ? Collections.emptySet() : result;
        });
        if (this.isStereotypeWithNameValue(type, metaTypes, attributes)) {
          Object value = attributes.get("value");
          if (value instanceof String) {
            String strVal = (String)value;
            if (StringUtils.hasLength(strVal)) {
              if (beanName != null && !strVal.equals(beanName)) {
                throw new IllegalStateException("Stereotype annotations suggest inconsistent component names: '" + beanName + "' versus '" + strVal + "'");
              }

              beanName = strVal;
            }
          }
        }
      }
    }

    return beanName;
  }

直接代码比较多其实就是去遍历类里面所有的注解,然后注解是否为component(在代码:this.isStereotypeWithNameValue(type, metaTypes, attributes)),再去判断value是否有设置值,有的话就用component注解里面的value作为beanName,如果没有就用类名第一个字母改成小写作为beanName(总的来说上面逻辑就是判断这个:如UserService如果component注解中value没有设置值那么beanName=userSerivce)

继续回到doscan方法里面的postProcessBeanDefinition方法
这个方法会给beandefinition里面赋一些初始的值(如是否懒加载这样的属性、@dependon等@Primary)

然后doscan里面的checkCandidate()方法是去检查容器中是否已经有beanName了初始化到BeanDefinitionHolder内,这里先跳过applyScopedProxyMode()方法beanDefinitions添加bdf然后注册到registerBeanDefinition里面最终注册到beandefinitionMap里面

protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
    if (!this.registry.containsBeanDefinition(beanName)) {
      return true;
    } else {
      BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
      BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
      if (originatingDef != null) {
        existingDef = originatingDef;
      }

      if (this.isCompatible(beanDefinition, existingDef)) {
        return false;
      } else {
        throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName + "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
      }
    }
  }

总的来说这个方法通常是返回true,也就是第一个if去判断容器中是否有这个beanName没有的话返回true,如果已经存在其实大部分情况都是直接抛异常,除非符合isCompatible这个条件才会return false(是否兼容的方法),
在多次扫描的情况下,第一次已经生成了一部分的bdf了,然后在第二次进到这个方法的时候会发现存在(existingDef )然后执行isCompatible方法,具体步骤是去判断两个bdf的资源(resource)是否相同,bdf不同但是resource相同表示class是兼容的然后返回false,不去注册到容器中。

因此spring的扫描逻辑到这里就结束了。
总结一下扫描的逻辑
扫描器->scan->doscan->findCandidateComponents(找到符合条件且带有component注解的类)->生成beanName(用类名首字母小写或者component里面value的值)->beanDefinition初始化一些属性->判断bdf与容器是否兼容(两个相同beanName的bdf是否有相同的resource)->注册到容器(兼容的bdf不注册)

2.创建非懒加载的单例bean
我们进到容器的refresh方法的finishBeanFactoryInitialization方法的preInstantiateSingletons()方法,顾名思义创建单例bean

   public void preInstantiateSingletons() throws BeansException {
    if (this.logger.isTraceEnabled()) {
      this.logger.trace("Pre-instantiating singletons in " + this);
    }

    List beanNames = new ArrayList(this.beanDefinitionNames);
    Iterator var2 = beanNames.iterator();

    while(true) {
      String beanName;
      Object bean;
      do {
        while(true) {
          RootBeanDefinition bd;
          do {
            do {
              do {
                if (!var2.hasNext()) {
                  var2 = beanNames.iterator();

                  while(var2.hasNext()) {
                    beanName = (String)var2.next();
                    Object singletonInstance = this.getSingleton(beanName);
                    if (singletonInstance instanceof SmartInitializingSingleton) {
                      StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
                      SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                      if (System.getSecurityManager() != null) {
                        AccessController.doPrivileged(() -> {
                          smartSingleton.afterSingletonsInstantiated();
                          return null;
                        }, this.getAccessControlContext());
                      } else {
                        smartSingleton.afterSingletonsInstantiated();
                      }

                      smartInitialize.end();
                    }
                  }

                  return;
                }

                beanName = (String)var2.next();
                bd = this.getMergedLocalBeanDefinition(beanName);
              } while(bd.isAbstract());
            } while(!bd.isSingleton());
          } while(bd.isLazyInit());

          if (this.isFactoryBean(beanName)) {
            bean = this.getBean("&" + beanName);
            break;
          }

          this.getBean(beanName);
        }
      } while(!(bean instanceof FactoryBean));

      FactoryBean factory = (FactoryBean)bean;
      boolean isEagerInit;
      if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
        SmartFactoryBean var10000 = (SmartFactoryBean)factory;
        ((SmartFactoryBean)factory).getClass();
        isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
      } else {
        isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
      }

      if (isEagerInit) {
        this.getBean(beanName);
      }
    }
  }

由于源码中do while嵌套太繁琐化简来看

代码中第一个do-while:

do{...} while(!(bean instanceof FactoryBean));

也就是不为FactoryBean的时候循环do里面的逻辑

代码中第二个do-while:

 do {
        while(true) {
          RootBeanDefinition bd;
          do {...}while(bd.isLazyInit());

          if (this.isFactoryBean(beanName)) {
            bean = this.getBean("&" + beanName);
            break;
          }

          this.getBean(beanName);
        }
      } while(!(bean instanceof FactoryBean));

非懒加载的bean走do循环逻辑
以此类推,最里面的do逻辑要求是非懒加载的单例bean+!isAbstract(且还得是抽象的beandefinition,正常情况定义的bean的beandefinition都不是抽象的只有在xml里面bean标签配置的bean abstract=true的时候创建的beandefintion是抽象的)
例如以下情况




那么userService的beandefinition继承了user的beandefinition,因此userService也是多例的
我们看到getMergedLocalBeanDefinition()方法

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    RootBeanDefinition mbd = (RootBeanDefinition)this.mergedBeanDefinitions.get(beanName);
    return mbd != null && !mbd.stale ? mbd : this.getMergedBeanDefinition(beanName, this.getBeanDefinition(beanName));
  }

会将user和userService的beanDefinition合并成一个rootBeanDefintiion,也就是去生成第三个beanDefintion并不会改变他们自己的beanDefintion,然后userService的属性会放在rootbdf里面,然后将rootbdf存到mergedBeanDefinitions里面去
然后我们在看到getMergedBeanDefinition()方法

protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) throws BeanDefinitionStoreException {
    synchronized(this.mergedBeanDefinitions) {
      RootBeanDefinition mbd = null;
      RootBeanDefinition previous = null;
      if (containingBd == null) {
        mbd = (RootBeanDefinition)this.mergedBeanDefinitions.get(beanName);
      }

      if (mbd == null || mbd.stale) {
        previous = mbd;
        if (bd.getParentName() == null) {
          if (bd instanceof RootBeanDefinition) {
            mbd = ((RootBeanDefinition)bd).cloneBeanDefinition();
          } else {
            mbd = new RootBeanDefinition(bd);
          }
        } else {
          BeanDefinition pbd;
          try {
            String parentBeanName = this.transformedBeanName(bd.getParentName());
            if (!beanName.equals(parentBeanName)) {
              pbd = this.getMergedBeanDefinition(parentBeanName);
            } else {
              BeanFactory parent = this.getParentBeanFactory();
              if (!(parent instanceof ConfigurableBeanFactory)) {
                throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without a ConfigurableBeanFactory parent");
              }

              pbd = ((ConfigurableBeanFactory)parent).getMergedBeanDefinition(parentBeanName);
            }
          } catch (NoSuchBeanDefinitionException var11) {
            throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, "Could not resolve parent bean definition '" + bd.getParentName() + "'", var11);
          }

          mbd = new RootBeanDefinition(pbd);
          mbd.overrideFrom(bd);
        }

        if (!StringUtils.hasLength(mbd.getScope())) {
          mbd.setScope("singleton");
        }

        if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
          mbd.setScope(containingBd.getScope());
        }

        if (containingBd == null && this.isCacheBeanMetadata()) {
          this.mergedBeanDefinitions.put(beanName, mbd);
        }
      }

      if (previous != null) {
        this.copyRelevantMergedBeanDefinitionCaches(previous, mbd);
      }

      return mbd;
    }
  }

这里的逻辑也比较复杂,我们直接看到
if (!beanName.equals(parentBeanName)) {
pbd = this.getMergedBeanDefinition(parentBeanName);
}
这里是用了递归有可能userService的父亲user还有父亲所以user要先跟那他的父亲去合并。核心就是合并逻辑。去生成一个新的rootbd

margedbdmap这个是非常重要的,后续很多beanName获取bd都是先去mbdMap里面去拿合并后的rootbd

我们再回到preInstantiateSingletons方法里的一段代码

              while(var2.hasNext()) {
                    beanName = (String)var2.next();
                    Object singletonInstance = this.getSingleton(beanName);
                    if (singletonInstance instanceof SmartInitializingSingleton) {
                      StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
                      SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                      if (System.getSecurityManager() != null) {
                        AccessController.doPrivileged(() -> {
                          smartSingleton.afterSingletonsInstantiated();
                          return null;
                        }, this.getAccessControlContext());
                      } else {
                        smartSingleton.afterSingletonsInstantiated();
                      }

                      smartInitialize.end();
                    }
                  }

这里是再去循环这些beanName,然后判断是否实现了SmartInitializingSingleton这个接口,如果实现了回去调用
类里面的afterSingletonsInstantiated()方法

然后我们在看到isFactoryBean()方法

public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
    String beanName = this.transformedBeanName(name);
    Object beanInstance = this.getSingleton(beanName, false);
    if (beanInstance != null) {
      return beanInstance instanceof FactoryBean;
    } else {
      return !this.containsBeanDefinition(beanName) && this.getParentBeanFactory() instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory)this.getParentBeanFactory()).isFactoryBean(name) : this.isFactoryBean(beanName, this.getMergedLocalBeanDefinition(beanName));
    }
  }

getSingleton()方法一开始是拿不到对象的,factoryBean生成的对象是两个对象分别是demoFactoryBean以及getObject返回的对象,getSingleton拿的是demoFactoryBean,然后判断是否实现FactoryBean
然后else逻辑是去判断本BeanFactory里面是有bd如果没有那么再去父BeanFactory里面去找bd(用代码解释如下)

AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(AppConfig.class);
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.setParent(parent);
       context.getBean("a1");

就是当context容器(子BeanFactory)里面去那a1的时候会先去判断是否有parentBeanFactory(上诉代码给context容器设置parent为parent容器)就会直接去parent里面找a1的bd


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/852132.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号