五陵年少金市东,银鞍白马渡春风。这篇文章主要讲述Spring源码浅析之bean实例的创建过程相关的知识,希望能为你提供帮助。
@TOC
在之前的文章内容中,简单介绍了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="https://www.songbingjia.com/android/翠花" />
<
constructor-arg index="1" value="https://www.songbingjia.com/android/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" />
factory-method=" getMemberFactoryMethod" >
< !--< constructor-arg index=" 0" value=https://www.songbingjia.com/android/" 你好" /> -->
< /bean>
- 指定工厂方法需要继承FactoryBean接口:
```java
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="https://www.songbingjia.com/android/翠花" />
<
constructor-arg index="1" value="https://www.songbingjia.com/android/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实例。
创建实例流程图下面,根据上面的源码内容,做一个简单的流程图,方便进行总结和查看:
文章图片
【Spring源码浅析之bean实例的创建过程】到此,getBean相关的内容已经介绍完毕了,下面就是真正创建bean实例的过程了。文章旨在记录学习内容和分享,如有不足还请见谅,文章中若有错误的地方,还望大佬不吝赐教,及时指正,共同学习,共同进步,互勉!
推荐阅读
- 鸿蒙开源第三方组件——日志工具组件Timber_ohos
- SpringCloud升级之路2020.0.x版-14.UnderTow AccessLog 配置介
- 鸿蒙卡片-物联网DTU污水液位计卡片
- Java ASM系列((053)opcode: math)
- netty系列之:自定义编码和解码器要注意的问题
- netty系列之:netty中的懒人编码解码器
- 执行效率高的代码-可以这样写出来~
- 华为面试官问我关于“多线程之内存模型”,看完这篇,自信满满!
- 鸿蒙内核之内存调测(动态内存池信息统计)