VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • Spring源码浅析之bean实例的创建过程(一)

在之前的文章内容中,简单介绍了bean定义的加载过程,下面这篇的主要内容就是bean实例的创建过程。

bean实例的创建方式

ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
context.getBean("beanDemo");

首先看到上面的代码,使用了getBean方法,那么创建bean的入口是不是在getBean里面呢?

通过之前的内容,可以知道,单例bean可以提前实例化,因为能够提高使用时的效率。原型bean,即多例bean则是在getBean的时候进行实例化的。而且单例bean和原型bean的实例化过程是没有区别的,都是通过getBean方法,在启动时提前实例化也是使用的getBean方法。

bean实例创建以及配置的方式如下:
image.png

  • 构造方法的方式

通过构造函数创建实例有两种方式,一种是无参构造函数,一种是有参构造函数

下面是无参构造函数的配置方式:

public class ConstructorBean {

    public ConstructorBean() {
        System.out.println("无参构造函数......");
    }
}
<bean id="constructorBean" class="edu.demo.spring.instantiate.ConstructorBean" />

下面是有参构造函数的配置方式:

public class ConstructorBean {

    public ConstructorBean(String name, int age) {
        System.out.println("带参构造函数......");
        System.out.println(name + "_" + age);
    }
}
<bean id="constructorBean" class="edu.demo.spring.instantiate.ConstructorBean">
   <constructor-arg index="0" value="翠花" />
   <constructor-arg index="1" value="18" />
</bean>

输出结果如下:

image.png

  • 静态工厂方法
public class InstantiateFactory {

    public static String getStaticFactoryMethod() {
       return "静态工厂方法创建bean......";
    }
}
<bean id="boyService" class="edu.demo.spring.instantiate.InstantiateFactory"
      factory-method="getStaticFactoryMethod" >
     <!--<property name="" ref=""></property>-->
</bean>
  • 非静态工厂方法
public class InstantiateFactory {

   public String getMemberFactoryMethod(String name) {
      return "非静态工厂方法创建bean......";
   }
}
<bean id="instantiateFactory" class="edu.demo.spring.instantiate.InstantiateFactory" />

<bean id="grilService" factory-bean="instantiateFactory"
   factory-method="getMemberFactoryMethod" >
   <!--<constructor-arg index="0" value="你好" />-->
</bean>
  • 指定工厂方法

需要继承FactoryBean接口:

public class BoyFactoryBean implements FactoryBean<Boy> {

   @Override
   public Boy getObject() throws Exception {
      return new Lad("niulang");
   }

   @Override
   public Class<?> getObjectType() {
      return Boy.class;
   }
}
<bean name="boyService2" class="edu.demo.spring.instantiate.BoyFactoryBean">
</bean>

如果要获取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());

分别输出如下:

image.png

实例化bean的流程

从AbstractApplicationContext类中的refresh()方法看起,这里有个步骤,是提前实例化一些单例bean:

//完成bean工厂的初始化,初始化所有非懒加载的单例bean
finishBeanFactoryInitialization(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<String> 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<String> 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<Boolean>) ((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> T doGetBean(
      String name, @Nullable Class<T> 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方法可以看到:

image.png

进入方法的第一步就执行了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<String, String> 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名称,下面来个小例子看一下:

<bean id="constructorBean" name="bean1,bean2,bean3,bean4" class="edu.demo.spring.instantiate.ConstructorBean">
   <constructor-arg index="0" value="翠花" />
   <constructor-arg index="1" value="18" />
</bean>

<alias name="bean2" alias="a"/>
ConstructorBean constructorBean = (ConstructorBean) context.getBean("a");

上面给constructorBean配置了4个别名bean1,bean2,bean3,bean4,而且给别名bean2又配置了一个别名a,也就是别名的别名。

debug后可以看到,这里传过来的就是别名bean2的别名a:

image.png
下面的图中,展示了bean定义别名的aliasMap:
image.png
现在清楚这里为啥使用do...while循环来获取标准的bean名称了吗,就是因为bean定义的别名,也可以有别名。当resolvedName为空,也就是说没有别名了,就会跳出循环,获取到真正的bean名称了。

接下来使用if...else分成了两个部分,先来看下第一部分:

// Eagerly check singleton cache for manually registered singletons.
//从缓存中获取已经实例化的单例bean
Object 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<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 单例工厂的缓存 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** 预加载的单例bean的缓存 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   //首先从单例bean的缓存中获取bean实例
   Object singletonObject = this.singletonObjects.get(beanName);
   //如果没有获取到并且这个bean正在创建中就执行下面的内容
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      //加锁
      synchronized (this.singletonObjects) {
         //从预加载的单例bean的缓存中获取bean实例
         singletonObject = this.earlySingletonObjects.get(beanName);、
         //如果还是没有获取到,而且是需要创建早期的引用的
         if (singletonObject == null && allowEarlyReference) {
            //从beanName中获取单例工厂
            ObjectFactory<?> 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<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);

/** Names of beans that have already been created at least once. */
private final Set<String> 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.
//获取依赖的bean
String[] 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. */
@Nullable
private Set<Exception> 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<String> singletonsCurrentlyInCreation =
      Collections.newSetFromMap(new ConcurrentHashMap<>(16));

/** Names of beans currently excluded from in creation checks. */
private final Set<String> 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<Object> 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<String> beanNameSet = new HashSet<>(2);
      beanNameSet.add((String) curVal);
      beanNameSet.add(beanName);
      this.prototypesCurrentlyInCreation.set(beanNameSet);
   }
   else {
      Set<String> beanNameSet = (Set<String>) 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<String> beanNameSet = (Set<String>) 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. */
@Nullable
volatile Boolean isFactoryBean;
//判断是不是工厂bean
if (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<String, Object> 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中获取即可:

@Nullable
protected 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<String, Object> 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<Object>) 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实例。

创建实例流程图

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

image.png

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

出处:https://www.cnblogs.com/fox2said/p/15165354.html


相关教程