Spring
是一个开源的设计层面框架,解决了业务逻辑层和其他各层的松耦合问题,将面向接口的编程思想贯穿整个系统应用,同时它也是Java工作中
必备技能之一…
前言 在 Spring解密 - XML解析 与 Bean注册 中,讲了 Bean的解析
,本章将详细讲解Spring中Bean的加载过程
,相比解析
而言,加载稍微复杂一点.
入口 1 2 3 4 5 6 7 8 9 public class Application { public static void main (String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml" ); Person person = context.getBean("person" , Person.class); System.out.println(person.toString()); } }
重点分析 context.getBean();
解密 在分析 Bean
的加载过程前,我们看看 BeanFactory
的由来,以及 getBean
所属的类是谁。磨刀不误砍柴工
BeanFactory 的由来 1.查看getBean()
的源码,此处的 getBeanFactory()
是怎么来的?
1 2 3 4 5 6 7 8 9 public class AbstractApplicationContext { @Override public <T> T getBean (String name, @Nullable Class<T> requiredType) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name, requiredType); } }
2.应用程序的上下文
在 new ClassPathXmlApplicationContext("bean.xml");
中,跳转到重载的构造方法中,我们会发现如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class ClassPathXmlApplicationContext { public ClassPathXmlApplicationContext ( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super (parent); setConfigLocations(configLocations); if (refresh) { refresh(); } } }
它的目的是将普通路径解析为 类(classpath)
路径资源名称。多个配置文件的情况下,后加载的 Bean
会覆盖先前定义好的 Bean
,这样做的目的是为了通过额外的XML文件来特意重写某个 Bean
。这里我们可以看到调用了一个 refresh()
,它的作用是什么 呢?
3.初始化
刷新容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class AbstractApplicationContext { @Override public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); } } protected ConfigurableListableBeanFactory obtainFreshBeanFactory () { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } }
初次加载完 bean.xml
后,肯定会进入到 refresh()
方法中,这个时候会做容器初始化的工作,也就是 标签解析、Bean加载
等等工作,由于本章重点介绍 Bean加载
,所以只贴了少量代码(看官莫急)
创建 DefaultListableBeanFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class AbstractRefreshableApplicationContext { @Override protected final void refreshBeanFactory () throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this .beanFactoryMonitor) { this .beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } @Override public final ConfigurableListableBeanFactory getBeanFactory () { synchronized (this .beanFactoryMonitor) { if (this .beanFactory == null ) { throw new IllegalStateException("BeanFactory not initialized or already closed - " + "call 'refresh' before accessing beans via the ApplicationContext" ); } return this .beanFactory; } } }
从上面的代码块中,我们可以看到 如果已经存在 beanFactory,将销毁旧的实例,然后在创建新的 DefaultListableBeanFactory
,最后 getBeanFactory()
就可以正常使用了。
Bean 加载 整个 Bean
的装载过程中,重点围绕 AbstractBeanFactory
,只要把它搞定剩下的就轻松了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 public abstract class AbstractBeanFactory { @Override public Object getBean (String name) throws BeansException { return doGetBean(name, null , null , false ); } protected <T> T doGetBean (final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference" ); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'" ); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } else { if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null ) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null ) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'" ); } registerDependentBean(dep, beanName); getBean(dep); } } if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { Object prototypeInstance = null ; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final 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 { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); 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); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null ) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" , ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; } }
整个代码块的内容还是不少的,接下来我们一步一步的分析。
转换 BeanName 1 2 3 4 5 final String beanName = transformedBeanName(name);protected String transformedBeanName (String name) { return canonicalName(BeanFactoryUtils.transformedBeanName(name)); }
去除 FactoryBean
的修饰符,最终取指定 alias
所表示的 beanName
。因为有可能获取到以 & 开头的 FactoryBean
,所以要进行转化(关于 BeanFactory
和 FactoryBean
后面会进行区分)
加载单例 检查缓存中是否存在 该 Bean
的单例(Bean默认的Scope = singleton)
,如容器初始化的时候或者其他地方已经调用过 getBean()
完成了初始化
1 Object sharedInstance = getSingleton(beanName);
缓存加载 Bean
默认在装载 Bean
的时候会先去检查 singletonObjects
是否存在,如果存在直接提取缓存的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class DefaultSingletonBeanRegistry { private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256 ); private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16 ); private final Map<String, Object> earlySingletonObjects = new HashMap<>(16 ); private final Set<String> registeredSingletons = new LinkedHashSet<>(256 ); @Nullable protected Object getSingleton (String beanName, boolean allowEarlyReference) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this .singletonObjects) { singletonObject = this .earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this .singletonFactories.get(beanName); if (singletonFactory != null ) { singletonObject = singletonFactory.getObject(); this .earlySingletonObjects.put(beanName, singletonObject); this .singletonFactories.remove(beanName); } } } } return singletonObject; } }
构建实例(无缓存情况)
缓存中没有,那就当场构建一个 bean
出来,可以看到 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
有两个参数,其中的 ObjectFactory
是怎么来的呢? 接着往下看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public Object getSingleton (String beanName, ObjectFactory<?> singletonFactory) { synchronized (this .singletonObjects) { Object singletonObject = this .singletonObjects.get(beanName); if (singletonObject == null ) { beforeSingletonCreation(beanName); singletonObject = singletonFactory.getObject(); afterSingletonCreation(beanName); addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null ); } }
构建 ObjectFactory
此处与其说是构建 ObjectFactory
,不如说是在创建一个单例 Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
创建 Bean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 public class AbstractAutowireCapableBeanFactory { @Override protected Object createBean (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'" ); } RootBeanDefinition mbdToUse = mbd; Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null ) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed" , ex); } try { Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null ) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed" , ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'" ); } return beanInstance; } catch (BeanCreationException ex) { throw ex; } catch (ImplicitlyAppearedSingletonException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation" , ex); } } }
在创建 Bean
之前,Spring
还做了不少工作。
判断创建的 bean
是否可以被实例化,这个类是否可以通过 ClassLoader
来载入,根据设置的 class
属性或根据 className
来解析 class
。
对覆盖进行标记并验证,在 Spring
配置中存在 lookup-mothod
和 replace-method
的,这两个配置的加载时将配置统一存放在 BeanDefinition
中的 methodOverrides
属性里,这个方法的操作也是针对于这两个配置的;
应用初始化前的后处理器,最后创建 bean
。在 createBean()
方法里执行完 resolveBeforeInstantiation
方法后,如果创建了代理且不为空的话就直接返回,否则需要进行常规 bean
的创建,这个创建过程是在 doCreateBean
中完成的
初始化 Bean 上面 createBean
交给了 doCreateBean
来创建 bean
(上面还有一个重要的方法getObjectForBeanInstance,在后面分析)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 protected Object doCreateBean (final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null ; if (mbd.isSingleton()) { instanceWrapper = this .factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed" , ex); } mbd.postProcessed = true ; } } boolean earlySingletonExposure = (mbd.isSingleton() && this .allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references" ); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed" , ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false ); if (earlySingletonReference != null ) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this .allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example." ); } } } } try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature" , ex); } return exposedObject; }
上面源码完成的操作可以概括为以下几点
RootBeanDefinition
是不是单例,如果是单例先移除缓存
实例化 bean
,将 RootBeanDefinition
转换为 BeanWrapper
使用 MergedBeanDefinitionPostProcessor
,Autowired注解
就是通过此方法实现类型的预解析;
解决循环依赖问题
在 populateBean()
中填充属性,配置在 XML
中的各种属性
注册到 DisposableBean
中
完成创建并返回 Bean
的实例
接下来我们看下 Spring
是如何创建 bean
实例的。跟踪 createBeanInstance()
方法
创建Bean实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 protected BeanWrapper createBeanInstance (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null ) { return obtainFromSupplier(instanceSupplier, beanName); } if (mbd.getFactoryMethodName() != null ) { return instantiateUsingFactoryMethod(beanName, mbd, args); } boolean resolved = false ; boolean autowireNecessary = false ; if (args == null ) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null ) { resolved = true ; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null , null ); } else { return instantiateBean(beanName, mbd); } } Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } return instantiateBean(beanName, mbd); }
可以看出如果在 RootBeanDefinition
中存在 factoryMethodName
属性,或者说配置文件中配置了 factory-method
,那么 Spring
会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args)
方法根据 RootBeanDefinition
中的配置生成bean实例。然后再解析构造方法并进行实例化,Spring
会根据参数及类型判断使用哪个构造方法进行实例化。判断调用哪个构造方法的过程会采用缓存机制,如果已经解析过则不需要重复解析而是从 RootBeanDefinition
中的属性 resolvedConstructorOrFactoryMethod
缓存的值去取,否则需再次解析。
populateBean 属性注入
这块代码比较多,有兴趣请自行跟进,就不贴出来了
在 populateBean
方法的中的主要处理流程:
InstantiationAwareBeanPostProcessor
处理器的 postProcessAfterInstantiation
方法控制程序是否继续填充属性;
根据注入类型提取依赖的 bean
,并存入 PropertyValues
中;
InstantiationAwareBeanPostProcessor
处理器的 postProcessPropertyValues
方法对属性在填充前再次处理(主要还是验证属性);
将所有 PropertyValues
中的属性填充到 BeanWrapper
中;
initializeBean 初始化Bean
学过 Spring
的都知道 bean
配置时有一个 init-method
属性,这个属性的作用是在 bean
实例化前调用 init-method
指定的方法进行需要的操作,现在就进入这个方法了;Spring
执行过 bean
的实例化,并且进行属性填充后,就会调用用户设定的初始化方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 protected Object initializeBean (final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null ) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null ; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null ), beanName, "Invocation of init method failed" , ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
最后加载完 Bean
并执行完初始化操作后,一个 bean
的加载基本就结束了。
增强的 Bean 通过上面的描述,我们已经知道了一个的 Bean
是如何初始化的,已经具备普通 Bean
的功能。但是 Spring
还提供了一种增强的 Bean(FactoryBean)
,具备 factory
能力的 Bean
,这个能力主要在 getObjectForBeanInstance
得到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class AbstractBeanFactory { protected Object getObjectForBeanInstance ( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null ; if (mbd == null ) { object = getCachedObjectForFactoryBean(beanName); } if (object == null ) { FactoryBean<?> factory = (FactoryBean<?>) beanInstance; if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; } }
关于 BeanFactory
和 FactoryBean
的区别:
BeanFactory: 容器的基本接口,是一个工厂,用来生产 Bean
FactoryBean: 是一个特殊的 Bean
,可以当作工厂使用的 Bean
循环依赖 上面有简单提到过 循环依赖(只有在单例情况下才会尝试解决循环依赖)。 无法解决就只能抛出 BeanCurrentlyInCreationException
异常
构造器循环依赖
无法解决,只能抛出 BeanCurrentlyInCreationException
异常
1 2 3 4 5 6 7 8 9 <bean id ="A" class ="com.battcn.A" > <constructor-arg index ="0" ref ="B" /> </bean > <bean id ="B" class ="com.battcn.B" > <constructor-arg index ="0" ref ="C" /> </bean > <bean id ="C" class ="com.battcn.C" > <constructor-arg index ="0" ref ="A" /> </bean >
setter 循环依赖
Spring
容器提前暴露了刚好完成的构造器注入,但未完成其他步骤 (如 setter 注入
的 bean
)。只能解决单例作用域的 bean
循环依赖。
1 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
prototype 范围的依赖处理
Spring
容器无法完成依赖注入,因为 Spring
容器不会缓存 prototype
作用域的 bean
,因此无法提前暴露一个创建中的 bean
。
1 2 3 4 5 6 7 8 9 <bean id ="A" class ="com.battcn.A" scope ="prototype" > <property name ="B" ref ="B" /> </bean > <bean id ="B" class ="com.battcn.B" scope ="prototype" > <property name ="C" ref ="C" /> </bean > <bean id ="C" class ="com.battcn.C" scope ="prototype" > <property name ="A" ref ="A" /> </bean >
总结 熬过几个无人知晓的秋冬春夏,撑过去一切都会顺着你想要的方向走…
说点什么 全文代码:https://gitee.com/battcn/battcn-spring-source/tree/master/Chapter4
个人QQ:1837307557
battcn开源群(适合新手):391619659
微信公众号:battcn
(欢迎调戏)