在之前的文章内容中,简单介绍了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("无参构造函数......");
}
}
<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>

输出结果如下:

  • 静态工厂方法
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());

分别输出如下:

实例化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方法可以看到:

进入方法的第一步就执行了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:



下面的图中,展示了bean定义别名的aliasMap:



现在清楚这里为啥使用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实例。

创建实例流程图

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

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

Spring源码浅析之bean实例的创建过程(一)的更多相关文章

  1. Spring源码浅析之bean实例的创建过程(二)

    在上一篇内容中,介绍了doGetBean方法的源码内容,知道了bean在创建的过程中,有三个范围,单例.多例.Scope,里面都使用到了createBean.下面本篇文章的主要内容,就是围绕creat ...

  2. spring源码浅析——IOC

    =========================================== 原文链接: spring源码浅析--IOC   转载请注明出处! ======================= ...

  3. Spring 源码分析之 bean 依赖注入原理(注入属性)

         最近在研究Spring bean 生命周期相关知识点以及源码,所以打算写一篇 Spring bean生命周期相关的文章,但是整理过程中发现涉及的点太多而且又很复杂,很难在一篇文章中把Spri ...

  4. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

  5. Spring源码-IOC部分-Bean实例化过程【5】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  6. 【Spring源码分析】Bean加载流程概览

    代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...

  7. Spring 源码分析之 bean 实例化原理

    本次主要想写spring bean的实例化相关的内容.创建spring bean 实例是spring bean 生命周期的第一阶段.bean 的生命周期主要有如下几个步骤: 创建bean的实例 给实例 ...

  8. 【Spring源码分析】Bean加载流程概览(转)

    转载自:https://www.cnblogs.com/xrq730/p/6285358.html 代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. ...

  9. Spring源码分析:Bean加载流程概览及配置文件读取

    很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事的都是Java Web的工作,对于程序员来说,一个Web项目用到Spring,只是配置一下配置文件而已 ...

随机推荐

  1. docker基本操作和部署

    #安装所需的软件包.yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data ...

  2. 探索互斥锁 Mutex 实现原理

    Mutex 互斥锁 概要描述 mutex 是 go 提供的同步原语.用于多个协程之间的同步协作.在大多数底层框架代码中都会用到这个锁. mutex 总过有三个状态 mutexLocked: 表示占有锁 ...

  3. 简单学习java内存马

    看了雷石的内存马深入浅出,就心血来潮看了看,由于本人java贼菜就不介绍原理了,本文有关知识都贴链接吧 前置知识 本次主要看的是tomcat的内存马,所以前置知识有下列 1.tomcat结构,tomc ...

  4. ARTS第六周

    第六周.后期补完,太忙了. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3.Tip:学习至少一个技术技巧4.Share:分享一篇有 ...

  5. Python3.7 lxml引入etree

    用xml代替lxml,Python3.7中已经没有etree这个模块了 import xml.etree.ElementTree as etree from lxml import etree 这种方 ...

  6. 【LeetCode】933.最近的请求次数

    933.最近的请求次数 知识点:队列: 题目描述 写一个 RecentCounter 类来计算特定时间范围内最近的请求. 请你实现 RecentCounter 类: RecentCounter() 初 ...

  7. JavaScript学习笔记:你必须要懂的原生JS(二)

    11.如何正确地判断this?箭头函数的this是什么? this是 JavaScript 语言的一个关键字.它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用. this的绑定规则 ...

  8. Linux 安装 Nodejs 的两种方式

    Linux 安装 Nodejs 的两种方式 目录 Linux 安装 Nodejs 的两种方式 一.压缩包安装 Nodejs 二.源码编译安装 Nodejs 一.压缩包安装 Nodejs 下载 Node ...

  9. 测试龙芯 LoongArch .NET之 使用 FastTunnel 做内网穿透远程计算机

    龙芯3A5000 已经上市,与龙芯3A5000配套的三大编译器GCC.LLVM.GoLang和三大虚拟机Java.JavaScript..NET均已完成开发,从老伙计哪里搞来一台3A5000 机器,安 ...

  10. Vue全局引入JS的方法

    两种情况: 1. js为ES5的写法时,如下(自定义的my.js): function fun(){ console.log('hello'); } Vue中的全局引入方式为,在index.html中 ...