Java码农之路 潜水
  • 13发帖数
  • 13主题数
  • 0关注数
  • 0粉丝
开启左侧

学Spring源码这么久了,必须要掌握的bean实例的创建过程,安排

[复制链接]
Java码农之路 发表于 2021-8-20 10:58:48 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
在之前的文章内容中,简朴先容了bean界说的加载过程,下面这篇的主要内容就是bean实例的创建过程。
bean实例的创建方式

ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");context.getBean("beanDemo");起首看到上面的代码,使用了getBean方法,那么创建bean的入口是不是在getBean里面呢?
通过之前的内容,可以知道,单例bean可以提前实例化,因为可以或许提高使用时的服从。原型bean,即多例bean则是在getBean的时间举行实例化的。而且单例bean和原型bean的实例化过程是没有区别的,都是通过getBean方法,在启动时提前实例化也是使用的getBean方法。
bean实例创建以及配置的方式如下:

                               
登录/注册后可看大图


  • 构造方法的方式
通过构造函数创建实例有两种方式,一种是无参构造函数,一种是有参构造函数
下面是无参构造函数的配置方式:
public class ConstructorBean {    public ConstructorBean() {        System.out.println("无参构造函数......");    }}下面是有参构造函数的配置方式:
public class ConstructorBean {    public ConstructorBean(String name, int age) {        System.out.println("带参构造函数......");        System.out.println(name + "_" + age);    }}      输出结果如下:

                               
登录/注册后可看大图


  • 静态工厂方法
public class InstantiateFactory {    public static String getStaticFactoryMethod() {       return "静态工厂方法创建bean......";    }}     

  • 非静态工厂方法
public class InstantiateFactory {   public String getMemberFactoryMethod(String name) {      return "非静态工厂方法创建bean......";   }}   

  • 指定工厂方法
需要继承FactoryBean接口:
public class BoyFactoryBean implements FactoryBean {   @Override   public Boy getObject() throws Exception {      return new Lad("niulang");   }   @Override   public Class getObjectType() {      return Boy.class;   }}如果要获取BoyFactoryBean自身,需要加上"&"前缀,否则返回的是getObject中的bean,这是由FactoryBean创建的bean实例
Object lsfb2 = context.getBean("boyService2");System.out.println(lsfb2);Object lsfb4 = context.getBean("&boyService2");System.out.println(lsfb4);BoyFactoryBean lsfb = (BoyFactoryBean) context.getBean("&boyService2");System.out.println(lsfb);System.out.println(lsfb.getObject());分别输出如下:

                               
登录/注册后可看大图

实例化bean的流程

从AbstractApplicationContext类中的refresh()方法看起,这里有个步骤,是提前实例化一些单例bean:
//完成bean工厂的初始化,初始化所有非懒加载的单例beanfinishBeanFactoryInitialization(beanFactory);点进去查看具体的实现:
/** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {   // Initialize conversion service for this context.   //实例化类型转换服务   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {      beanFactory.setConversionService(            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));   }   // Register a default embedded value resolver if no bean post-processor   // (such as a PropertyPlaceholderConfigurer bean) registered any before:   // at this point, primarily for resolution in annotation attribute values.   //确保beanFacotory持有嵌入值的解析器   if (!beanFactory.hasEmbeddedValueResolver()) {      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));   }   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.   // 提前实例化LoadTimeWeaverAware beans   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);   for (String weaverAwareName : weaverAwareNames) {      getBean(weaverAwareName);   }   // Stop using the temporary ClassLoader for type matching.   beanFactory.setTempClassLoader(null);   // Allow for caching all bean definition metadata, not expecting further changes.   // 冻结配置,要举行实例化了,bean界说信息就不能举行更改了   beanFactory.freezeConfiguration();   // Instantiate all remaining (non-lazy-init) singletons.   // 实例化单例bean   beanFactory.preInstantiateSingletons();}然后会进入preInstantiateSingletons方法:
    /** 按照注册顺序存放的bean界说名称聚集 */    private volatile List beanDefinitionNames = new ArrayList(256);  // Iterate over a copy to allow for init methods which in turn register new bean definitions.   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.   //获取到所有的bean界说名称   List beanNames = new ArrayList(this.beanDefinitionNames);根据上面的代码可以看到,这个方法刚一进来,就获取所有的bean界说名称,这个bean界说的list使用了volatile关键字举行修饰,关于volatile不清楚的可以看下之前线程方面的文章。
// Trigger initialization of all non-lazy singleton beans...//触发所有非懒加载单例bean的初始化for (String beanName : beanNames) {   //获取合并之后的bean界说信息   RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);   //如果bean界说不是抽象的,而且是单例的,不是懒加载的,就继续实行   if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {      //如果是工厂bean就继续实行,否则直接实行getBean方法      if (isFactoryBean(beanName)) {         //获取bean,这里的bean是一个工厂bean         Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);         if (bean instanceof FactoryBean) {            FactoryBean factory = (FactoryBean) bean;            //判断是不是急需实例化的            boolean isEagerInit;            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {               isEagerInit = AccessController.doPrivileged(                     (PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit,                     getAccessControlContext());            }            else {               isEagerInit = (factory instanceof SmartFactoryBean &&                     ((SmartFactoryBean) factory).isEagerInit());            }            //如果这个bean急需实例化,就调用getBean方法            if (isEagerInit) {               getBean(beanName);            }         }      }      else {         //获取平凡bean         getBean(beanName);      }   }}FactoryBean是什么,上面已经有了简朴的使用,FactoryBean虽然也是一个bean,但是它是一个可以生产bean的bean。如果直接使用getBean获取的是它生产的bean,以是需要使用getBean(& + beanName)才能获取这个工厂bean。
doGetBean方法先容

protected  T doGetBean(      String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly)      throws BeansException {}这里传过来了四个参数,第一个参数name就是bean界说的名称,requiredType是bean所需要的类型,args是显式传过来的参数,typeCheckOnly是否类型查抄。
args指的就是下面代码中的参数:
ConstructorBean constructorBean = (ConstructorBean) context.getBean("constructorBean", new Object[]{1,2,3});使用刚刚上面的示例,然后debug到doGetBean方法可以看到:

                               
登录/注册后可看大图

进入方法的第一步就实行了transformedBeanName方法:
String beanName = transformedBeanName(name);Object bean;这个transformedBeanName方法就是获取到标准的bean界说名称,什么是标准的bean界说名称呢?因为在配置bean界说的时间,可以给这个bean界说一些别名。
当使用getBean("别名")也是可以获取到这个bean界说的。主要的原因就是底层使用了aliasMap,这个aliasMap的key值就是别名,value值就是真正的bean界说名称。
/** Map from alias to canonical name. */private final Map aliasMap = new ConcurrentHashMap(16);/** * Return the bean name, stripping out the factory dereference prefix if necessary, * and resolving aliases to canonical names. * @param name the user-specified name * @return the transformed bean name */protected String transformedBeanName(String name) {   return canonicalName(BeanFactoryUtils.transformedBeanName(name));}这里又调用了BeanFactoryUtils.transformedBeanName和canonicalName两个方法:
/** * 返回bean名称,须要时去掉工厂解引用前缀 * @param name the name of the bean * @return the transformed name * @see BeanFactory#FACTORY_BEAN_PREFIX */public static String transformedBeanName(String name) {   Assert.notNull(name, "'name' must not be null");   //如果bean名称不包含&前缀,就直接返回   if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {      return name;   }   //去除bean名称的解引用前缀,也就是&前缀   return transformedBeanNameCache.computeIfAbsent(name, beanName -> {      do {         beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());      }      while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));      return beanName;   });}/** * 这个方法的作用,就是获取到真正的bean名称 * @param name the user-specified name * @return the transformed name */public String canonicalName(String name) {   String canonicalName = name;   // Handle aliasing...   String resolvedName;   do {      resolvedName = this.aliasMap.get(canonicalName);      if (resolvedName != null) {         canonicalName = resolvedName;      }   }   while (resolvedName != null);   return canonicalName;}canonicalName里面使用了do...while循环来获取真正的bean名称,下面来个小例子看一下:
      ConstructorBean constructorBean = (ConstructorBean) context.getBean("a");上面给constructorBean配置了4个别名bean1,bean2,bean3,bean4,而且给别名bean2又配置了一个别名a,也就是别名的别名。
debug后可以看到,这里传过来的就是别名bean2的别名a:

                               
登录/注册后可看大图


下面的图中,展示了bean界说别名的aliasMap:


                               
登录/注册后可看大图


现在清楚这里为啥使用do...while循环来获取标准的bean名称了吗,就是因为bean界说的别名,也可以有别名。当resolvedName为空,也就是说没有别名了,就会跳出循环,获取到真正的bean名称了。

接下来使用if...else分成了两个部分,先来看下第一部分:
// Eagerly check singleton cache for manually registered singletons.//从缓存中获取已经实例化的单例beanObject sharedInstance = getSingleton(beanName);//如果bean实例存在且显式传过来的参数是空的就实行下面的代码if (sharedInstance != null && args == null) {   if (logger.isTraceEnabled()) {      if (isSingletonCurrentlyInCreation(beanName)) {         logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +               "' that is not fully initialized yet - a consequence of a circular reference");      }      else {         logger.trace("Returning cached instance of singleton bean '" + beanName + "'");      }   }   //这里,是判断这个bean是不是FactoryBean,如果是FactoryBean,那么就要从FactoryBean中创建一个实例   bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}下面先看下getSingleton这个方法:
/** 单例bean的缓存 */private final Map singletonObjects = new ConcurrentHashMap(256);/** 单例工厂的缓存 */private final Map singletonFactory = this.singletonFactories.get(beanName);            //如果工厂不为空            if (singletonFactory != null) {               //获取bean               singletonObject = singletonFactory.getObject();               //放入预加载的单例bean的缓存中               this.earlySingletonObjects.put(beanName, singletonObject);               //把bean从singletonFactories中移除,               //因为已经在上面加入到earlySingletonObjects了,以是singletonFactories就不需要了               this.singletonFactories.remove(beanName);            }         }      }   }   return singletonObject;}如果上面的方式没有获取到bean实例,那么就走下面的else方法:
// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {   throw new BeanCurrentlyInCreationException(beanName);}起首这里,是判断原型bean是否已经在构建中了,来检测循环依赖的,比如创建bean1的时间需要依赖bean2,而创建bean2的过程中又依赖bean1,那么这样就会抛出异常。
下面的代码,就是判断父工厂的:
// Check if bean definition exists in this factory.//起首,获取父工厂BeanFactory parentBeanFactory = getParentBeanFactory();//如果父工厂不为空,而且本地又不包含这个bean界说,那就从父工厂中获取if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {   // Not found -> check parent.   //这一步就是还原原来的bean名称,因为有factoryBean的存在,   //上面把它的前缀去掉,这里要加回来   String nameToLookup = originalBeanName(name);   //下面就是通过父类去创建bean实例   if (parentBeanFactory instanceof AbstractBeanFactory) {      return ((AbstractBeanFactory) parentBeanFactory).doGetBean(            nameToLookup, requiredType, args, typeCheckOnly);   }   else if (args != null) {      // Delegation to parent with explicit args.      return (T) parentBeanFactory.getBean(nameToLookup, args);   }   else if (requiredType != null) {      // No args -> delegate to standard getBean method.      return parentBeanFactory.getBean(nameToLookup, requiredType);   }   else {      return (T) parentBeanFactory.getBean(nameToLookup);   }}从上面的代码可以看到,parentBeanFactory.getBean,这里又使用了getBean方法,可见也是递归调用。
if (!typeCheckOnly) {   markBeanAsCreated(beanName);}上面的代码,是判断,如果这里不仅仅是做类型查抄,那这里就记载一下,记载该bean已经被创建了。下面是markBeanAsCreated方法:
/** Map from bean name to merged RootBeanDefinition. */private final Map mergedBeanDefinitions = new ConcurrentHashMap(256);/** Names of beans that have already been created at least once. */private final Set alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap(256));protected void markBeanAsCreated(String beanName) {   //起首,判断已经创建的bean聚会合是否包含该bean   if (!this.alreadyCreated.contains(beanName)) {      //加锁      synchronized (this.mergedBeanDefinitions) {         //再次判断,双重检锁         if (!this.alreadyCreated.contains(beanName)) {            // Let the bean definition get re-merged now that we're actually creating            // the bean... just in case some of its metadata changed in the meantime.            //这里,是把合并的bean界说清除掉,让bean界说重新合并,            //为了防止这个bean界说发生了变化            clearMergedBeanDefinition(beanName);            //把beanName加入到已经创建的聚会合            this.alreadyCreated.add(beanName);         }      }   }}然后再次进入下面的代码:
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.//获取依赖的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {   //循环遍历依赖的bean   for (String dep : dependsOn) {      //判断是不是循环依赖,是的话就抛出异常      if (isDependent(beanName, dep)) {         throw new BeanCreationException(mbd.getResourceDescription(), beanName,               "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");      }      //注册依赖的bean      registerDependentBean(dep, beanName);      try {         //获取到依赖的bean         getBean(dep);      }      catch (NoSuchBeanDefinitionException ex) {         throw new BeanCreationException(mbd.getResourceDescription(), beanName,               "'" + beanName + "' depends on missing bean '" + dep + "'", ex);      }   }}这里先是获取合并后的bean界说,然后检测该bean是否是抽象的,如果是的话,就会抛出异常,这个判断在checkMergedBeanDefinition方法内。
然后是看这个bean是否依赖了其他bean,如果有依赖,就把依赖的bean注册到一个依赖的map中,然后调用getBean方法,先把依赖的bean实例化。
最后,如果上面都判断结束,还是没有获取到bean实例的话,就实行下面的代码来创建bean实例:
// Create bean instance.// Scope的处理:单例、原型、其他//判断是否单例if (mbd.isSingleton()) {   //获取单例bean,如果获取不到就举行创建,然后缓存到单例bean的聚会合   sharedInstance = getSingleton(beanName, () -> {      try {         return createBean(beanName, mbd, args);      }      catch (BeansException ex) {         // Explicitly remove instance from singleton cache: It might have been put there         // eagerly by the creation process, to allow for circular reference resolution.         // Also remove any beans that received a temporary reference to the bean.         destroySingleton(beanName);         throw ex;      }   });   //举行工厂bean的处理   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}//原型bean的处理else if (mbd.isPrototype()) {   // It's a prototype -> create a new instance.   Object prototypeInstance = null;   try {      //多例bean的循环依赖查抄,而且做记载      beforePrototypeCreation(beanName);      //创建bean      prototypeInstance = createBean(beanName, mbd, args);   }   finally {     //开释循环依赖查抄的记载      afterPrototypeCreation(beanName);   }   //举行工厂bean的处理   bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}//其他范围bean的处理else {   String scopeName = mbd.getScope();   if (!StringUtils.hasLength(scopeName)) {      throw new IllegalStateException("No scope name defined for bean " + beanName + "'");   }   Scope scope = this.scopes.get(scopeName);   if (scope == null) {      throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");   }   try {      Object scopedInstance = scope.get(beanName, () -> {        //循环依赖查抄,而且做记载         beforePrototypeCreation(beanName);         try {            //创建bean            return createBean(beanName, mbd, args);         }         finally {            //开释循环依赖查抄的记载            afterPrototypeCreation(beanName);         }      });      //举行工厂bean的处理      bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);   }   catch (IllegalStateException ex) {      throw new BeanCreationException(beanName,            "Scope '" + scopeName + "' is not active for the current thread; consider " +            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",            ex);   }}上面的创建,分成了三个部分,分别是单例、多例和其他范围的bean,大致的处理过程是一样的,都调用了createBean方法举行创建。
getSingleton方法

下面来看下单例bean的getSingleton方法:
/** * Return the (raw) singleton object registered under the given name, * creating and registering a new one if none registered yet. * @param beanName the name of the bean * @param singletonFactory the ObjectFactory to lazily create the singleton * with, if necessary * @return the registered singleton object */public Object getSingleton(String beanName, ObjectFactory singletonFactory) {}这个方法用来获取单例bean,而且会调用创建bean的方法。
synchronized (this.singletonObjects) {   Object singletonObject = this.singletonObjects.get(beanName);}起首举行了加锁,然后从singletonObjects中获取单例bean,singletonObjects上面已经说过,里面存放了已经实例化的单例bean聚集,这里先从singletonObjects获取,如果获取不到,再举行创建。
/** Flag that indicates whether we're currently within destroySingletons. */private boolean singletonsCurrentlyInDestruction = false;/** Collection of suppressed Exceptions, available for associating related causes. */@Nullableprivate Set suppressedExceptions;//如果获取不到该单例bean,那么就举行创建if (singletonObject == null) {    //判断该单例bean是否正在烧毁,是的话就抛异常    if (this.singletonsCurrentlyInDestruction) {       throw new BeanCreationNotAllowedException(beanName,             "Singleton bean creation not allowed while singletons of this factory are in destruction " +             "(Do not request a bean from a BeanFactory in a destroy method implementation!)");    }    if (logger.isDebugEnabled()) {       logger.debug("Creating shared instance of singleton bean '" + beanName + "'");    }    //单例bean创建之前的处理,也是举行记载    beforeSingletonCreation(beanName);    //是否新创建的单例bean    boolean newSingleton = false;    //记载在创建过程中产生的异常,可能是的,这个我猜的,哈哈    boolean recordSuppressedExceptions = (this.suppressedExceptions == null);    if (recordSuppressedExceptions) {       this.suppressedExceptions = new LinkedHashSet();    }}然后看下beforeSingletonCreation这个方法
/** Names of beans that are currently in creation. */private final Set singletonsCurrentlyInCreation =      Collections.newSetFromMap(new ConcurrentHashMap(16));/** Names of beans currently excluded from in creation checks. */private final Set inCreationCheckExclusions =      Collections.newSetFromMap(new ConcurrentHashMap(16));protected void beforeSingletonCreation(String beanName) {   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {      throw new BeanCurrentlyInCreationException(beanName);   }}举行了判断和添加,inCreationCheckExclusions是排除的bean名称聚集,也就是说这个bean不会被创建。singletonsCurrentlyInCreation记载当前正在创建的bean名称。
下面就是举行创建的代码:
try {   //singletonFactory就是实行上面的创建bean代码   singletonObject = singletonFactory.getObject();   //创建完成后,标记为新的单例bean   newSingleton = true;}然后下面的代码就是举行一些缓存:
finally {   if (recordSuppressedExceptions) {      this.suppressedExceptions = null;   }   //移除记载   afterSingletonCreation(beanName);}//如果是新的单例bean,就举行一些缓存if (newSingleton) {   addSingleton(beanName, singletonObject);}看下afterSingletonCreation方法,就是把当前的bean从正在创建的聚会合移除掉
protected void afterSingletonCreation(String beanName) {   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");   }}然后下面就是缓存的方法了:
protected void addSingleton(String beanName, Object singletonObject) {   synchronized (this.singletonObjects) {      this.singletonObjects.put(beanName, singletonObject);      this.singletonFactories.remove(beanName);      this.earlySingletonObjects.remove(beanName);      this.registeredSingletons.add(beanName);   }}这个方法就比较简朴了,把已经实例化的单例bean加入到singletonObjects聚集,因为已经实例化了,以是从singletonFactories和earlySingletonObjects中移除了,而且还加入到了registeredSingletons聚会合。
原型bean

下面来看下原型bean的处理:
/** Names of beans that are currently in creation. */private final ThreadLocal prototypesCurrentlyInCreation =      new NamedThreadLocal("Prototype beans currently in creation");protected void beforePrototypeCreation(String beanName) {   Object curVal = this.prototypesCurrentlyInCreation.get();   if (curVal == null) {      this.prototypesCurrentlyInCreation.set(beanName);   }   else if (curVal instanceof String) {      Set beanNameSet = new HashSet(2);      beanNameSet.add((String) curVal);      beanNameSet.add(beanName);      this.prototypesCurrentlyInCreation.set(beanNameSet);   }   else {      Set beanNameSet = (Set) curVal;      beanNameSet.add(beanName);   }}protected void afterPrototypeCreation(String beanName) {   Object curVal = this.prototypesCurrentlyInCreation.get();   if (curVal instanceof String) {      this.prototypesCurrentlyInCreation.remove();   }   else if (curVal instanceof Set) {      Set beanNameSet = (Set) curVal;      beanNameSet.remove(beanName);      if (beanNameSet.isEmpty()) {         this.prototypesCurrentlyInCreation.remove();      }   }}从上面的源码,可以看到,prototypesCurrentlyInCreation使用到了ThreadLocal,可以制止线程重复创建bean,afterPrototypeCreation是把这个标记给移除掉。而scope和原型bean这块的处理是一样的。
getObjectForBeanInstance方法

最后呢,还有一个方法没有看,下面就来看下getObjectForBeanInstance这个方法吧。
protected Object getObjectForBeanInstance(      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {}这里传来了四个参数,beanInstance是bean实例,name是原始的bean名称,也就是可能包含&前缀,beanName是标准的bean名称,mbd是合并之后的bean界说信息。
/** Package-visible field for caching if the bean is a factory bean. */@Nullablevolatile Boolean isFactoryBean;//判断是不是工厂beanif (BeanFactoryUtils.isFactoryDereference(name)) {   //如果是NullBean,直接返回   if (beanInstance instanceof NullBean) {      return beanInstance;   }   //如果不是FactoryBean类型,直接抛出异常   //是工厂bean,但是不是FactoryBean类型   if (!(beanInstance instanceof FactoryBean)) {      throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());   }   //设置isFactoryBean标记,标记该bean是工厂bean   if (mbd != null) {      mbd.isFactoryBean = true;   }   //返回bean实例   return beanInstance;}判断是不是工厂bean的方法,比较简朴,判断是不是以&开头的:
public static boolean isFactoryDereference(@Nullable String name) {   return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));}如果当前bean实例不是FactoryBean类型,直接返回
// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.if (!(beanInstance instanceof FactoryBean)) {   return beanInstance;}如果上面都没有获取到bean实例,则实行下面的代码:
/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */private final Map factoryBeanObjectCache = new ConcurrentHashMap(16);Object object = null;if (mbd != null) {   mbd.isFactoryBean = true;}else {   //从缓存中获取bean   object = getCachedObjectForFactoryBean(beanName);}if (object == null) {   // Return bean instance from factory.   FactoryBean factory = (FactoryBean) beanInstance;   // Caches object obtained from FactoryBean if it is a singleton.   //如果bean界说为空,且beanDefinitionMap中包含该bean名称,则获取合并后的bean界说   if (mbd == null && containsBeanDefinition(beanName)) {      mbd = getMergedLocalBeanDefinition(beanName);   }   //是否是用户自界说的bean   boolean synthetic = (mbd != null && mbd.isSynthetic());   //从FactoryBean中获取bean   object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;getCachedObjectForFactoryBean方法比较简朴,直接从缓存的map中获取即可:
@Nullableprotected Object getCachedObjectForFactoryBean(String beanName) {   return this.factoryBeanObjectCache.get(beanName);}再然后就是getObjectFromFactoryBean,从FactoryBean中来获取对象:
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess)这里传过来三个参数,factory就是上面传过来的factoryBean,beanName就是配置里面界说的bean名称,shouldPostProcess的意思是:是否允许bean举行后置处理。
if (factory.isSingleton() && containsSingleton(beanName)) {  synchronized (getSingletonMutex()) {   }}起首上来就是判断,这个factory是不是单例的,单例bean的聚会合是否包含这个bean名称,如果都满足就实行下面的代码。
/** 由FactoryBean创建的单例对象的缓存:对象的FactoryBean名称 */private final Map factoryBeanObjectCache = new ConcurrentHashMap(16);//起首从缓存中获取Object object = this.factoryBeanObjectCache.get(beanName);//如果缓存中不存在就继续实行if (object == null) {   object = doGetObjectFromFactoryBean(factory, beanName);   // Only post-process and store if not put there already during getObject() call above   // (e.g. because of circular reference processing triggered by custom getBean calls)   //再次从缓存中获取,由于循环引用可能导致这个bean已经在缓存中了   Object alreadyThere = this.factoryBeanObjectCache.get(beanName);   //获取到了就直接赋值   if (alreadyThere != null) {      object = alreadyThere;   }   else {      if (shouldPostProcess) {          //当前bean正在创建直接返回,暂时不做后置处理         if (isSingletonCurrentlyInCreation(beanName)) {            // Temporarily return non-post-processed object, not storing it yet..            return object;         }         //循环依赖查抄,做记载         beforeSingletonCreation(beanName);         try {            //对这个bean做后置处理            object = postProcessObjectFromFactoryBean(object, beanName);         }         catch (Throwable ex) {            throw new BeanCreationException(beanName,                  "Post-processing of FactoryBean's singleton object failed", ex);         }         finally {            //循环依赖查抄,移除            afterSingletonCreation(beanName);         }      }      //当前bean是否在单例bean的聚会合,如果是的就缓存      if (containsSingleton(beanName)) {         this.factoryBeanObjectCache.put(beanName, object);      }   }}//返回bean实例return object;再然后就是else里面的处理,代码量较少,if里面已经有相同的代码了。
Object object = doGetObjectFromFactoryBean(factory, beanName);if (shouldPostProcess) {   try {      object = postProcessObjectFromFactoryBean(object, beanName);   }   catch (Throwable ex) {      throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);   }}return object;doGetObjectFromFactoryBean方法:
private Object doGetObjectFromFactoryBean(FactoryBean factory, String beanName) throws BeanCreationException {   Object object;   try {      //举行权限的验证      if (System.getSecurityManager() != null) {         AccessControlContext acc = getAccessControlContext();         try {            object = AccessController.doPrivileged((PrivilegedExceptionAction) factory::getObject, acc);         }         catch (PrivilegedActionException pae) {            throw pae.getException();         }      }      else {         //这里,直接调用了getObject方法         object = factory.getObject();      }   }   catch (FactoryBeanNotInitializedException ex) {      throw new BeanCurrentlyInCreationException(beanName, ex.toString());   }   catch (Throwable ex) {      throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);   }   // Do not accept a null value for a FactoryBean that's not fully   // initialized yet: Many FactoryBeans just return null then.   if (object == null) {      if (isSingletonCurrentlyInCreation(beanName)) {         throw new BeanCurrentlyInCreationException(               beanName, "FactoryBean which is currently in creation returned null from getObject");      }      object = new NullBean();   }   return object;}这部分的代码,就是从factoryBean中获取到getObject里面的bean实例。
创建实例流程图

下面,根据上面的源码内容,做一个简朴的流程图,方便举行总结和查看:

                               
登录/注册后可看大图

到此,getBean相关的内容已经先容完毕了,下面就是真正创建bean实例的过程了。文章旨在记载学习内容和分享,如有不足还请见谅,文章中若有错误的地方,还望大佬不吝赐教,实时指正,共同砚习,共同进步,互勉!

精彩评论11

就叫我李665 发表于 2021-8-20 11:21:56 | 显示全部楼层
收藏
通往大数据的地铁 发表于 2021-8-20 11:43:07 | 显示全部楼层
转发了
顶级饭团 发表于 2021-8-21 07:24:57 | 显示全部楼层
转发了
资源帝在彼岸 发表于 2021-8-21 16:52:37 | 显示全部楼层
转发了
君主不是他 发表于 2021-8-21 11:18:41 | 显示全部楼层
转发了
靠近你温暖我yh 发表于 2021-8-20 12:21:26 | 显示全部楼层
转发了
奋斗的道路上只有奔跑 发表于 2021-8-21 06:40:09 | 显示全部楼层
转发了
未来趋势-逍遥飞鹤 发表于 2021-8-20 12:35:35 | 显示全部楼层
转发了
hiecho 发表于 2021-8-21 07:49:10 | 显示全部楼层
转发了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

猜你喜欢
在线客服邮箱
wxcy#wkgb.net

邮箱地址#换为@

Powered by 创意电子 ©2018-现在 专注资源实战分享源码下载站联盟商城