学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实例创建以及配置的方式如下:
https://p9.toutiaoimg.com/large/pgc-image/ccfbf6b39b8c49528252e7ebb7cef5db
[*]构造方法的方式
通过构造函数创建实例有两种方式,一种是无参构造函数,一种是有参构造函数
下面是无参构造函数的配置方式:
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); }} 输出结果如下:
https://p26.toutiaoimg.com/large/pgc-image/536eb792c469420c8db43ba2a197dfde
[*]静态工厂方法
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());分别输出如下:
https://p9.toutiaoimg.com/large/pgc-image/1e83112218904257a741120a6ffcfdeb
实例化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方法先容
protectedT 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方法可以看到:
https://p3.toutiaoimg.com/large/pgc-image/7943fb9253b941a3a420bbe73632d505
进入方法的第一步就实行了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:
https://p9.toutiaoimg.com/large/pgc-image/34262194963448b7a7bf96a078783200
下面的图中,展示了bean界说别名的aliasMap:
https://p26.toutiaoimg.com/large/pgc-image/5318a2ff16724a9e8265ab5bde334ccc
现在清楚这里为啥使用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实例。
创建实例流程图
下面,根据上面的源码内容,做一个简朴的流程图,方便举行总结和查看:
https://p9.toutiaoimg.com/large/pgc-image/f7d11b33c93f4f538fdae1731dbb664f
到此,getBean相关的内容已经先容完毕了,下面就是真正创建bean实例的过程了。文章旨在记载学习内容和分享,如有不足还请见谅,文章中若有错误的地方,还望大佬不吝赐教,实时指正,共同砚习,共同进步,互勉! 收藏 转发了 转发了 转发了 转发了 转发了 转发了 转发了 转发了
页:
[1]
2