Spring解析之finishBeanFactoryInitialization即初始化单例bean

Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean Python微信订餐小程序课程视频 https://edu.youkuaiyun.com/course/detail/36074 Python实战量化交易理财系统 https://edu.youkuaiyun.com/course/detail/35475 Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Spring是如何解决循环依赖? 今天解读Spring核心方法refresh()中最最重 阅读详情

今天解读Spring核心方法refresh()中最最重要的一个方法finishBeanFactoryInitialization()方法,该方法负责初始化所有的单例bean。

finishBeanFactoryInitialization()方法位于refresh()中下标为8的位置。

到目前为止,应该说是是 BeanFactory 已经创建完成,并且所有的实现了 BeanFactoryPostProcessor 接口的 Bean 都已经初始化并且其中的 postProcessBeanFactory(factory) 方法已经得到回调执行了。而且 Spring 已经“手动”注册了一些特殊的 Bean,如 environment、systemProperties 等。

剩下的就是初始化 singleton beans 了,大多数我们的业务中都是单例bean,就像我们写的@Controller、@Service的类(没有设置懒加载的)都是在这个地方初始化,以供我们使用,如果没有设置懒加载,那么 Spring 会在接下来初始化所有的 singleton beans。

我们先看一下refresh()的源码,大概看下finishBeanFactoryInitialization(beanFactory)所处的位置。

@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.//1、刷新前的准备prepareRefresh();// Tell the subclass to refresh the internal bean factory.//2、将会初始化 BeanFactory、加载 Bean、注册 BeanConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.//3、设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 beanprepareBeanFactory(beanFactory);try {//4、模板方法// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.//执行BeanFactory后置处理器invokeBeanFactoryPostProcessors(beanFactory);// 5、Register bean processors that intercept bean creation.//注册bean后置处理器registerBeanPostProcessors(beanFactory);// Initialize message source for this context.//国际化initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.//6、模板方法--springboot实现了这个方法onRefresh();// Check for listener beans and register them.//7、注册监听器registerListeners();// Instantiate all remaining (non-lazy-init) singletons.//8、完成bean工厂的初始化**方法重要**********************************************finishBeanFactoryInitialization(beanFactory);//9、 Last step: publish corresponding event.finishRefresh();}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.

我们深入finishBeanFactoryInitialization(beanFactory)中,里面的调用线路错综复杂,还望读者可以做好心理准备。

/** * 负责单例bean的初始化 * 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.//最先初始化名字为 conversionService的类,conversionService类 它用来将前端传过来的参数和后端的 controller 方法上的参数进行绑定的时候用//尤其是用于非基础类型的转换if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(//初始化在getBean()方法中实现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.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.// 先初始化 LoadTimeWeaverAware 类型的 Bean aop相关注:大概有个印象,以后解析aop会和它串起来。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.//freeze的单词意思是冻结,这个时候已经开始预初始化, bean 定义解析、加载、注册先停止beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.//开始初始化beanFactory.preInstantiateSingletons();}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.

该方法是判断bean的一系列是不是属于某个类型的bean,如果是就调用getBean()方法,如果不是,就调用beanFactory.preInstantiateSingletons()进行初始化,我们先把getBean()放一放,重点看一看beanFactory.preInstantiateSingletons()方法。

@Overridepublic void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// 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.// this.beanDefinitionNames 保存了所有的 beanNamesList<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...//// 下面这个循环,触发所有的非懒加载的 singleton beans 的初始化操作for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 非抽象、非懒加载的 singletons。如果配置了 'abstract = true',那是不需要初始化的if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 处理 FactoryBean (负责初始化工厂的bean)if (isFactoryBean(beanName)) {// FactoryBean 的话,在 beanName 前面加上 ‘&’ 符号//此处调用getBean()方法Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;// 判断当前 FactoryBean 是否是 SmartFactoryBean 的实现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());}if (isEagerInit) {getBean(beanName);}}}else {// 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...// 到这里说明所有的非懒加载的 singleton beans 已经完成了初始化// 如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的,那么在这里得到回调//如果你想在单例bean初始化后做一些事 那就实现该接口for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}}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.

preInstantiateSingletons()方法的主要任务是进行初始化的,在初始化前同样是一系列判断,如,是否是懒加载的,是否是一个factorybean(一个特别的bean,负责工厂创建的bean),最后调用getBean()方法。

其中有个插曲是否实现了SmartInitializingSingleton接口,将接口让你可以在bean初始化后做一些事,我们写一个简单的实例测试一下。

其他地方读者看注释了解一下即可,我们开始继续深入getBean()方法。

getBean()方法内部调用了doGetBean()我们直接看doGetBean方法。

// 我们在剖析初始化 Bean 的过程,但是 getBean 方法我们经常是用来从容器中获取 Bean 用的,注意切换思路,// 已经初始化过了就从容器中直接返回,否则就先初始化再返回protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// 获取一个 “正统的” beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&’),// 一个是别名问题,因为这个方法是 getBean,获取 Bean 用的,你要是传一个别名进来,是完全可以的String beanName = transformedBeanName(name);// 返回值Object bean;// Eagerly check singleton cache for manually registered singletons.// 检查下是不是已经创建过了Object sharedInstance = getSingleton(beanName);// 这里说下 args ,虽然看上去一点不重要。前面我们一路进来的时候都是 getBean(beanName),// 所以 args 传参其实是 null 的,但是如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Beanif (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 的话,直接返回 sharedInstance,// 如果是 FactoryBean 的话,返回它创建的那个实例对象bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.// 创建过了此 beanName 的 prototype 类型的 bean,那么抛异常,// 往往是因为陷入了循环引用 哦,原来之前的循环依赖都是在这抛的异常,再有问题就不是无头苍蝇了if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.// 检查一下这个 BeanDefinition 在容器中是否存在 BeanDefinition既是包含了bean的一系列信息BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.// 如果当前容器不存在这个 BeanDefinition,试试父容器中有没有String nameToLookup = originalBeanName(name);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);}}if (!typeCheckOnly) {// typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。markBeanAsCreated(beanName);}/* * 稍稍总结一下: * 到这里的话,要准备创建 Bean 了,对于 singleton 的 Bean 来说,容器中还没创建过此 Bean; * 对于 prototype 的 Bean 来说,本来就是要创建一个新的 Bean。 */try {RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 先初始化依赖的所有 Bean,这个很好理解。// 注意,这里的依赖指的是 depends-on 中定义的依赖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);try {// 先初始化被依赖项getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.// 如果是 singleton scope 的,创建 singleton 的实例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {// 执行创建 Bean,详情继续深入// 第三个参数 args 数组代表创建实例需要的参数,不就是给构造方法用的参数,或者是工厂 Bean 的参数嘛,不过要注意,在我们的初始化阶段,args 是 null。// 这回我们要到一个新的类了 AbstractAutowireCapableBeanFactory,看类名,AutowireCapable?类名是不是也说明了点问题了。// 主要是为了以下场景,采用 @Autowired 注解注入属性值: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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// 如果是 prototype scope 的,创建 prototype 的实例else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);// 执行创建 BeanprototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}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 {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;}}// Check if required type matches the type of the actual bean instance.// 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了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.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) 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.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.162.163.164.165.166.167.168.169.170.171.172.173.174.175.176.177.178.179.180.181.182.183.184.185.186.187.188.189.190.191.192.193.194.195.196.

具体的实例化过程在createBean()方法中,我们继续深入createBean()方法。

@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.// 确保 BeanDefinition 中的 Class 被加载Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.// 准备方法覆写,这里又涉及到一个概念:MethodOverrides,它来自于 bean 定义中的 <lookup-method />// 和 <replaced-method />,如果读者感兴趣,回到 bean 解析的地方看看对这两个标签的解析。try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理,// 在 《Spring AOP 源码分析》那篇文章中有解释,这里先跳过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 {// 重头戏,创建 beanObject beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}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.

我们继续往里看 doCreateBean 这个方法,这个调用过程是真的深。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {// 说明不是 FactoryBean,这里实例化 Bean,这里非常关键,细节之后再说**********instanceWrapper = createBeanInstance(beanName, mbd, args);}Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.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;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.// 下面这块代码是为了解决循环依赖的问题,这是个重头戏,解决循环依赖问题boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {// 这一步也是非常关键的,这一步负责属性装配,因为前面的实例只是实例化了,并没有设值,这里就是设值***************populateBean(beanName, mbd, instanceWrapper);// 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?// 这里就是处理 bean 初始化完成后的各种回调**************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 " +"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}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.

到这里,我们已经分析完了 doCreateBean 方法,总的来说,我们已经说完了整个初始化流程。

在实例化bean后有一个特别重要的知识点,也是面试中最常问的,Spring怎么解决循环依赖问题?核心代码就在这个方法里面。

循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图:

doCreateBean 方法有三个核心流程。

(1)createBeanInstance:实例化,其实也就是调用对象的构造方法实例化对象

(2)populateBean:填充属性,这一步主要是多bean的依赖属性进行填充

(3)initializeBean:调用spring xml中的init 方法。

从上面讲述的单例bean初始化步骤我们可以知道,循环依赖主要发生在第一、第二步。也就是构造器循环依赖和field循环依赖。

那么我们要解决循环引用也应该从初始化过程着手,对于单例来说,在Spring容器整个生命周期内,有且只有一个对象,所以很容易想到这个对象应该存在Cache中,Spring为了解决单例的循环依赖问题,使用了三级缓存。

我们看一下getSingleton方法。

该方法还依赖于三个map,这三个map就是三级缓存。

/** Cache of singleton objects: bean name to bean instance. *///单例对象的cacheprivate final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);/** Cache of singleton factories: bean name to ObjectFactory. */// 单例对象工厂的cacheprivate final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);/** Cache of early singleton objects: bean name to bean instance. *///提前曝光的单例对象的Cacheprivate final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);1.2.3.4.5.6.7.8.9.10.11.
@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {// Quick check for existing instance without full singleton lockObject singletonObject = this.singletonObjects.get(beanName);//判断当前单例bean是否正在创建中,也就是没有初始化完成(比如A的构造器依赖了B对象所以得先去创建B对象// 或则在A的populateBean过程中依赖了B对象,得先去创建B对象,这时的A就是处于创建中的状态。if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {singletonObject = this.earlySingletonObjects.get(beanName);// 是否允许从singletonFactories中通过getObject拿到对象if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}}}return singletonObject;}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.

分析getSingleton()的整个过程,Spring首先从一级缓存singletonObjects中获取。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。

如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,如果获取到了则:

this.earlySingletonObjects.put(beanName, singletonObject);                        this.singletonFactories.remove(beanName);                        1.2.3.

从singletonFactories中移除,并放入earlySingletonObjects中。其实也就是从三级缓存移动到了二级缓存。

从上面三级缓存的分析,我们可以知道,Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache。

里就是解决循环依赖的关键,这段代码发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用。

这样做有什么好处呢?

让我们来分析一下“A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象”这种循环依赖的情况。

A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是总比没有好呀),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。

此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,而且更加幸运的是,由于B拿到了A的对象引用,所以B现在hold住的A对象完成了初始化。

知道了这个原理时候,肯定就知道为啥Spring不能解决“A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象”这类问题了!因为加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决。

接下来我们挑 doCreateBean 中的三个细节出来说说。一个是创建 Bean 实例的 createBeanInstance 方法,一个是依赖注入的 populateBean 方法,还有就是回调方法 initializeBean。

这三个方法也是极其复杂的,读者有兴趣可以继续的深入进去。

1、 createBeanInstance 方法

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// Make sure bean class is actually resolved at this point.// 确保已经加载了此 classClass<?> 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) {// 采用工厂方法实例化,不熟悉这个概念的读者请看附录,注意,不是 FactoryBeanreturn instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...// 如果不是第一次创建,比如第二次创建 prototype bean。// 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化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);}}// Candidate constructors for autowiring?// 判断是否采用有参构造函数Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {// 构造函数依赖注入return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?ctors = mbd.getPreferredConstructors();if (ctors != null) {// 构造函数依赖注入return autowireConstructor(beanName, mbd, ctors, null);}// No special handling: simply use no-arg constructor.// 调用无参构造函数return instantiateBean(beanName, mbd);}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.

看一下instantiateBean方法是怎么做的。

protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {try {Object beanInstance;if (System.getSecurityManager() != null) {beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),getAccessControlContext());}else {// 实例化beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);}// 包装一下,返回BeanWrapper bw = new BeanWrapperImpl(beanInstance);initBeanWrapper(bw);return bw;}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.

我们可以看到,关键的地方在于:beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

里面是具体是实例化过程,我们进去看看。

@Overridepublic Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.// 如果不存在方法覆写,那就使用 java 反射进行实例化,否则使用 CGLIB,// 方法覆写 请参见附录"方法注入"中对 lookup-method 和 replaced-method 的介绍if (!bd.hasMethodOverrides()) {Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Class<?> clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);}else {constructorToUse = clazz.getDeclaredConstructor();}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}// 利用构造方法进行实例化return BeanUtils.instantiateClass(constructorToUse);}else {// Must generate CGLIB subclass.// 存在方法覆写,利用 CGLIB 来完成实例化,需要依赖于 CGLIB 生成子类,这里就不展开了。// tips: 因为如果不使用 CGLIB 的话,存在 override 的情况 JDK 并没有提供相应的实例化支持return instantiateWithMethodInjection(bd, beanName, owner);}}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.

到这里,我们就算实例化完成了。我们开始说怎么进行属性注入。

2、populateBean 方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {if (bw == null) {if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}else {// Skip property population phase for null instance.return;}}// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}}// bean 实例的所有属性都在这里了PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);int resolvedAutowireMode = mbd.getResolvedAutowireMode();// 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}// 这里有个非常有用的 BeanPostProcessor 进到这里: AutowiredAnnotationBeanPostProcessor// 对采用 @Autowired、@Value 注解的依赖进行设值,这里的内容也是非常丰富的pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}if (pvs != null) {// 设置 bean 实例的属性值applyPropertyValues(beanName, mbd, bw, pvs);}}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.

属性注入完成后,这一步其实就是处理各种回调了,这块代码比较简单。

3、 initializeBean方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {// 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {// BeanPostProcessor 的 postProcessBeforeInitialization 回调wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {// 处理 bean 中定义的 init-method,// 或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法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()) {// BeanPostProcessor 的 postProcessAfterInitialization 回调//BeanPostProcessor 的两个回调都发生在这边,只不过中间处理了 init-methodwrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}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.

自此,Spring实例化单例非懒加载bean的过程也就完成了,这也是Spirng最最重要的方法了。在我们的日常使用Spring中,定义好各个类,然后在上面加上,@Controller,@Service,Autowired等注解,这些注解是怎么起作用的呢?

C#实战:如何用winmm.dll打造毫秒级高精度定时器(附完整代码) 本文详细介绍了在C#中利用winmm.dll实现毫秒级高精度定时器的完整方案。针对.NET内置定时器精度不足的问题,通过调用timeSetEvent等原生API,提供了超越系统时钟中断周期的精准定时能力。文章包含核心原理剖析、完整的封装类代码以及音视频处理、游戏开发等场景下的实战应用与性能调优指南。 阅读详情

相关推荐

RAG——从0到1快速搭建RAG应用

本文介绍了基于LangChain框架构建RAG(检索增强生成)应用的技术方案,涵盖核心模块选型与实现流程。技术栈包括:LangChain应用框架、pypdf文档解析、RecursiveCharacterTextSplitter文本分块、bge-small-zh-v1.5向量模型、Faiss向量库和通义千问大模型。文章详细说明了开发环境配置步骤,包括虚拟环境创建、依赖库安装和模型下载。核心代码分为索引、检索、生成三大流程,索引流程完成PDF文档解析、分块和向量化存储;检索流程实现查询向量化和相似度匹配;生成流

小志的博客 589

Spring循环依赖以及解决方式

Spring为了解决单例的循环依赖问题,使用了三级缓存。 这三级缓存分别指: 3 singletonFactories : 单例对象工厂的cache 2 earlySingletonObjects :提前暴光的单例对象的Cache 1 singletonObjects:单例对象的cache Spring首先从一级缓存singletonObjects中获取。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。如果还是获取不到且允许singletonFactorie

aishenla的博客 617

高光谱知识(1)-高光谱成像技术的理解

系列文章目录 高光谱技术可以获得待观测目标或场景的连续单色光谱图像,并通过空间维(x, y)数据和光谱维(λ)数据共同组成三维观测数据立方体,从而为研究人员提供探测目标或场景中的每一个点的空间和光谱特征细节。这种兼具相机的高分辨成像能力和光谱仪的高光谱分辨能力使得高光谱被广泛应用于测绘遥感、目标识别、环境监测与评估、临床影像诊断、过程监控等任务中,并在地理、空间、海洋、气候、大气、农业、植被、生态、医药、安防、制造与色度等多个领域中发挥巨大作用。 文章目录系列文章目录前言一、按获取数据的过程划分二、按照光

Echo_Code的博客 1万+

Spring源码学习笔记(十二)、finishBeanFactoryInitialization

/ 初始化所有的singleton beans(lazy-init的除外)初始化所有的singleton beans(lazy-init的除外)

dongdong199033的博客 564

深入浅出横向联邦学习、纵向联邦学习、联邦迁移学习

深入浅出解析横向联邦学习(Horizontal Federated Learning)、纵向联邦学习(Vertical Federated Learning)和联邦迁移学习(Federated Transfer Learning)有多个机构(比如几家不同的银行,或者几家医院)都拥有一些数据,他们希望联合起来训练一个更强大的机器学习模型,但出于隐私保护或法规要求,他们不能直接把数据共享出来。联邦学习就是为了解决这个问题而提出的。它的核心思想是“数据不动模型动”,即数据保留在本地,参与方共同训练模型。

frostmelody 全网同名,大家多多关注呀~ 持续分享优质内容! 2458

PlatformIO串口监视器波特率配置实战:从乱码到清晰输出的关键步骤

本文针对PlatformIO串口监视器常见的乱码问题,深入解析了其根源在于波特率不匹配。文章核心在于指导开发者通过修改项目根目录下的platformio.ini配置文件,正确设置monitor_speed参数,确保与代码中Serial.begin()的波特率一致,从而实现从乱码到清晰输出的关键步骤。此外,还介绍了其他实用的串口监控配置与常见避坑指南。

weixin_29183637的博客 388

Spring源码之finishBeanFactoryInitialization()

方法是 Spring 启动过程中的一个关键步骤,用于完成 BeanFactory 的初始化。在这个方法中,会执行一系列的操作,包括实例化非延迟加载的单例 Bean、处理 Bean 的生命周期回调方法等,以确保应用程序能够正常运行。

苟且。的博客 683

c语言串口编程详解

串口: 一种异步通信接口,通常用于低速数据传输。RS-232: 最常见的串口标准,定义了电气特性、连接器和信号线。UART: 通用异步收发传输器,是实现串口通信的硬件模块。通过以上内容,你应能够理解并实现C语言在Windows和Linux平台上的串口编程。希望这本手册能帮助你在实际项目中顺利进行串口通信开发。如果有任何疑问或需要进一步的帮助,请随时提问。

jkzyx123的博客 2221

Spring启动流程源码之finishBeanFactoryInitialization

Spring启动流程源码之finishBeanFactoryInitialization

qq_43418737的博客 929

ICLR 2022)ODConv:即插即用的动态卷积 (附代码)

一定程度上讲,ODConv可以视作CondConv的延续,将CondConv中一个维度上的动态特性进行了扩展,同时了考虑了空域、输入通道、输出通道等维度上的动态性,故称之为全维度动态卷积。ODConv是一种动态卷积算法,它的原理是在卷积过程中,根据输入数据的特征动态地调整卷积核的形状和大小,以适应不同的输入数据。具体来说,ODConv通过引入一个可学习的形变模块,根据输入数据的特征动态地调整卷积核的形状和大小,从而提高了卷积神经网络的性能。此外,相比常规卷积,动态卷积的卷积核参数往往是其n倍。

PLANTTHESON的博客 2万+

工业相机的检测原理课件(建议收藏)

本课件为各位工程师详细介绍了工业相机的视觉检测原理 ,旨在为工程师调试工业相机的视觉检测原理时提供理论性指导。

Bamboo265925的博客 498

【七】springboot启动源码 - finishBeanFactoryInitialization

第252行,transformedBeanName(name),用于返回真实beanName,如果是beanName以&开头(表示factoryBean),去掉&并返回。preInstantiateSingletons方法,遍历beanDefinitionNames,通过mergedBeanDefinitions来获取每一个RootBeanDefinition,并判断他是否是factorybean,如果不是,调用getBean()方法。进入getMergedLocalBeanDefinition方法。

qq_36382225的博客 481

Unity引擎开发:复杂动作系统_动作捕捉数据的应用与整合

通过以上步骤,我们可以在Unity中有效地应用和整合动作捕捉数据,以实现更加真实和流畅的动画效果。从导入文件格式的选择,到预处理和优化,再到实时应用和调试验证,每一步都至关重要。希望本文能帮助你在Unity项目中更好地利用动作捕捉数据,提升动画质量和性能。

chenlz2007的博客 957

IOC容器初始化过程中单例Bean的预实例化

在容器的refresh方法中我们可以看到finishBeanFactoryInitialization方法,该方法就是实例化所有非懒加载实例 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2ef69b46ca234789afae30476f546451.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/b06d25f96aac4597b1510be24b0bdca8.png) ## ① finishBeanFactoryIniti

小小默:进无止境 7920

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring中refresh分析之finishBeanFactoryInitialization方法详解

接上文[Spring中refresh分析之registerListeners方法详解](https://blog.youkuaiyun.com/J080624/article/details/76823915)我们分析过registerListeners后,本文分析finishBeanFactoryInitialization方法。 该方法其将会拿到所有的beanDefinitionNames,遍历beanNames,其非抽象、是单例、未配置lazy_init属性或其值非true那么就会触发getBean的操作;遍.

小小默:进无止境 1896

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

spring源码IOC初始化过程-第11个方法源码分析-finishBeanFactoryInitialization(beanFactory);

前言 这篇文章分析的是spring(环境,容器,上下文)初始化过程种调用的最重要的方法之一 finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) 这个方法中解决了Bean循环依赖,依赖的Bean经过AOP如何处理等问题 由于spring容器初始化过程十分复杂,防止迷茫,请有选择的查看! 其他方法的源码请查看我的其他文章 11、finishBeanFactoryInitialization(beanFa

qq_37391371的博客 264

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

深入理解Spring系列之六:bean初始化

《深入理解Spring系列之四:BeanDefinition装载前奏曲》中提到,对于非延迟单例bean的初始化在finishBeanFactoryInitialization(beanFactory)中完成。进入这个方法,代码如下。protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFa

JavaQ 1044

Spring源码十三:非懒加载单例Bean

今天我们看下Spring是如何初始化非延迟加载单例的Bean首先我先回到refresh方法中: 我们将目光回到refresh方法中的,finishBeanFactoryInitialization方法: 上述代码注释很清晰,finishBeanFactoryInitialization方法其实只是做了一些比较基础的初始化工作,核心还得看下preInstantiateSingletons方法。 上述内容,首先是遍历所有已经注册到Spring容器中的BeanDefiniton对象(在obtainBe

Jeremy程序员 530

Spring 源码(五)初始化所有单例Bean,并注册到容器(Bean的生命周期)

在这之前我们先来看下refresh()方法,它完整的描述了整个ApplicationContext的初始化过程。这里看起来更像是对容器进行初始化的模板或者提纲。 @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonit...

xiaolyuh的专栏 564

Spring注解驱动开发第46讲——Spring IOC容器创建源码解析(六)之初始化所有剩下的单实例bean(上)

写在前面 在前面几讲中,我们已经对IOC容器创建过程中的大部分方法进行过研究,其中比较核心的方法就是如下两个: invokeBeanFactoryPostProcessors方法:该方法在《Spring注解驱动开发第42讲——Spring容器创建源码解析(二)之执行BeanFactoryPostProcessor》这一讲中已经详细讲过了,要是还有不清楚的同学,可以查阅这篇文章哟! registerBeanPostProcessors方法:该方法在《Spring注解驱动开发第43讲——Spring容器创建源

李阿昀的博客 1866

SpringBoot bean解析之refresh方法(五)

这里主要着重看看refresh方法调用的finishBeanFactoryInitialization,初始化所有剩下的单例bean; /** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */ protected...

lhf2112的博客 1874

Spring源码之ApplicationContext(九)初始化剩余的单例

这里所指的剩余的单例,其实就是非延迟加载单例。在Spring的源码中,是通过finishBeanFactoryInitialization的方法来执行的。我们按照惯例,先来看一张时序图。 首先Spring还是调用AbstractApplicationContext中的finishBeanFactoryInitialization的方法。这个方法中包括了ConversionServic

owen_william的博客 918

Spring【版本5.2.2】容器初始化过程(五)finishBeanFactoryInitialization

11.finishBeanFactoryInitialization 篇幅原因,可能会删除一些不重要的代码,是不重要,不是没用。 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 1. 判断是否有bdName为conversionService的bd(...

屹想天开 293

10_finishBeanFactoryInitialization

finishBeanFactoryInitialization 的作用就是初始化剩余的所有单实例bean。除了一些需要提前初始化的类。比如前面实现了BeanDefinitionRegistryPostProcessor(在invokeBeanFactoryPostProcessors方法的时候)。通过beanFactory.getBean提前获取的。最后的都是在该方法中完成创建。 pr...

hu619016140的博客 281

spring 完成bean的最后创建原理

调用finishbeanfactoryinitialzation完成bean最后的创建 点进此方法 发现最终会执行下面这个方法 就是初始化最后的单实例bean 继续跟进 可以看到 先得到 所有beandefinitions 然后再开始创建对象 如果是factorybean 就调用 getobject 创建 bean不是则 调用下面的方法进行创建bean 调用dogetbean创建 先获...

wzx01234567890的博客 573
上一篇: 你了解Java中的并发编程吗?
下一篇: 看完不信你还不懂MVCC原理详解
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值