- 浏览: 50339 次
- 性别:
- 来自: 南京
文章分类
最新评论
AbstractAutowireCapableBeanFactory#doCreateBean
DefaultSingletonBeanRegistry#getSingleton
AbstractAutoProxyCreator#
1.为什么要用三级缓存而不用二级缓存
一个设计良好的系统应该不会经常出现循环引用的情况的,在一开始就设置早期引用浪费系统资源;
2.为什么三级缓存中放入ObjectFactory,而不是bean
为了扩展,生成事务代理或其他代理,以便是代理也可以循环引用
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 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)); //此处表示是否抛出早期引用,以便循环引用时使用,放在三级缓存的singtonFactories里面 //存在循环引用是采用调用ObjectFactory.getObject if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { 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) { //此处从二级缓存的earlySingtonObjects中获取,如何不为空表示,存在循环引用 //在doGetBean方法中,会将三级缓存的singtonFactories调用ObjectFactory.getObject放入到二级缓存的earlySingtonObjects中 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { //如果相等表示,早期引用的bean(即设置到其他bean中的bean引用即为此处的早期引用) //因为exposedObject = earlySingletonReference;最终都是一个引用 //事务代理属于此类循环引用的实例,事务代理时在AbstractAutoProxyCreater的早期引用中创建的 if (exposedObject == bean) { exposedObject = earlySingletonReference; } //如果能够容忍创建的bean有多个版本,则可以设置allowRawInjectionDespiteWrapping=true,但这样就破换了spring的单例原则,不建议使用 //hasDependentBean此处表示是否存在引用创建中的bean的其他bean(姑且是beanOther),如果存在则beanOther引用了bean的早期引用,与最终生成的bean是不一致的,肯定不对 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) { //此处的TypeCheckOnly=true的场景暂时没有想到待补充,也请路过的博友能够指点一二 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."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
DefaultSingletonBeanRegistry#getSingleton
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); // 该singletonFactory不为空,在doCreateBean阶段已经放入了ObjectFactory //此处调用getObject方法生成早期引用,并放入二级环境earlySingletonObjects if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
AbstractAutoProxyCreator#
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { Object cacheKey = getCacheKey(bean.getClass(), beanName); //此处this.earlyProxyReferences中放入参与早期引用的缓存,在postProcessAfterInitialization中就不用再次创建了,保证了doCreateBean中exposedObject == bean //他们生成的代理功能本质上是一样的都是getAdvicesAndAdvisorsForBean获取的切面 //但仅限于AbstractAutoProxyCreator的子类生成的代理是可以循环引用的,例如事务属于此类 //其他类型的代理或自定义的代理可能没有实现earlyProxyReferences类似功能,导致exposed!=bean if (!this.earlyProxyReferences.containsKey(cacheKey)) { this.earlyProxyReferences.put(cacheKey, Boolean.TRUE); } return wrapIfNecessary(bean, beanName, cacheKey); } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.containsKey(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
1.为什么要用三级缓存而不用二级缓存
一个设计良好的系统应该不会经常出现循环引用的情况的,在一开始就设置早期引用浪费系统资源;
2.为什么三级缓存中放入ObjectFactory,而不是bean
为了扩展,生成事务代理或其他代理,以便是代理也可以循环引用
发表评论
-
spring容器
2019-07-14 08:47 305private final ServletContainer ... -
spring容器
2019-07-13 23:35 0spring容器与springmvc容器 73 ... -
spring源码学习系列2.6-spring ioc原理-codes
2019-03-05 22:56 487web.xml <listener> < ... -
spring源码学习系列3.4-spring mvc原理-codes
2019-01-21 22:46 296本篇章从核心类角度解读springmvc的原理 web.xm ... -
spring源码学习系列4.2-spring aop原理-codes
2018-12-04 22:29 561jdk: Proxy InvocationHandler ... -
spring源码学习系列4.1-spring实现对ibatis的事务管理
2018-09-17 15:44 578事务由spring管理,可以理解为由spring管理数据库连接 ... -
spring源码学习系列4-3种常用的自动代理创建器
2018-09-02 15:48 5703种自动代理器是 AnnotationAwareAspectJ ... -
spring源码学习系列1.2-spring事务代理深入分析2
2018-05-27 19:46 451提示: BeanPostProcessor AopUtils ... -
spring源码学习系列2.5-ApplicationContext初始化-设计模式
2018-05-08 15:17 519ApplicationContext容器的初始化可以通过模板方 ... -
spring源码学习系列3.3-DispatcherServlet初始化-设计模式
2018-05-07 11:12 622springmvc的核心是DispatcherServlet ... -
封装spring-security
2018-01-23 19:33 518github地址: https://github.com/ne ... -
eclipse导入spring源码
2018-05-12 07:20 980spring在git上的项目时gradle管理jar包的,所以 ... -
spring源码学习系列3.2.3-异常页面拦截机制
2017-07-29 19:07 766前序:本文的意义在于了解 tomcat处理异常 请求访问 ... -
spring源码学习系列3.2.2-How to bind String to Date
2017-07-17 12:40 596springmvc开发中,经常需将界面日期数据(String) ... -
spring源码学习系列3.2.1-command对象的绑定
2017-05-28 12:00 981在<spring源码学习系列3.2-handlerAda ... -
spring源码学习系列3.2-handlerAdapter执行
2017-05-28 12:01 409DispatcherServlet#doDispatch中调用 ... -
spring源码学习系列3.1-handlerMapping初始化
2017-05-28 11:56 701SimpleUrlHandlerMapping的继承体系 or ... -
spring源码学习系列2.4-finishRefresh会做什么
2017-05-06 16:36 578spring容器初始化完成后,调用finishRresh 该 ... -
spring源码学习系列3-springmvc原理
2017-05-28 11:56 456问题: springmvc是如何控 ... -
spring源码学习系列2-容器初始化入口-refresh
2017-04-23 21:33 477context=XmlWebApplicationContex ...
相关推荐
spring-ai-core 0.8.1,解决大家使用2023.0.1.0 版本 Spring Cloud Alibaba 依赖,代码依赖下载报错问题, <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies <version>...
赠送Maven依赖信息文件:spring-context-support-1.0.10.pom; 包含翻译后的API文档:spring-context-support-1.0.10-javadoc-API文档-中文(简体)版.zip; Maven坐标:...
赠送Maven依赖信息文件:spring-context-support-5.0.5.RELEASE.pom; 包含翻译后的API文档:spring-context-support-5.0.5.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework:spring-...
赠送Maven依赖信息文件:spring-data-commons-2.5.5.pom; 包含翻译后的API文档:spring-data-commons-2.5.5-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.data:spring-data-commons:2.5.5;...
《深入解析jasypt-spring-boot-starter 3.0.5依赖的POM与JAR》 在Java开发领域,构建和管理依赖是至关重要的环节。jasypt-spring-boot-starter是一个流行的安全库,它允许开发者在Spring Boot应用中轻松地实现加密...
commons-pool2-2.3.jar,jedis-2.8.0.jar,spring-data-redis-1.6.0.RELEASE.jar,spring-session-1.1.1.RELEASE.jar,Spring-data-redis(Version 1.6.0.RC1)中文版.pdf
解决这个问题的方法通常是将`spring-cglib-repack-3.2.0.jar`和`spring-objenesis-repack-2.1.jar`添加到你的项目构建路径中,如果是Maven或Gradle项目,可以在pom.xml或build.gradle文件中声明对应的依赖。...
赠送Maven依赖信息文件:spring-messaging-5.0.8.RELEASE.pom; 包含翻译后的API文档:spring-messaging-5.0.8.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework:spring-messaging:5.0.8...
通过继承spring-boot-dependencies,spring-boot-starter-parent可以提供一系列的依赖项管理功能,包括依赖项版本管理、插件配置等。 spring-boot-starter-parent的主要特点是它可以帮助开发者快速构建Spring Boot...
赠送Maven依赖信息文件:spring-data-commons-2.6.1.pom; 包含翻译后的API文档:spring-data-commons-2.6.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.data:spring-data-commons:2.6.1;...
赠送Maven依赖信息文件:spring-security-config-5.5.2.pom; 包含翻译后的API文档:spring-security-config-5.5.2-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-...
标题 "spring-boot-starter-parent-1.5.13.RELEASE.zip" 提供的信息表明,这是一个与Spring Boot相关的压缩包,具体来说是Spring Boot的起步依赖(Starter Parent)的一个版本,版本号为1.5.13.RELEASE。Spring Boot...
赠送Maven依赖信息文件:spring-context-5.3.12.pom; 包含翻译后的API文档:spring-context-5.3.12-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.springframework:spring-context:5.3.12; 标签:...
标题中的"spring-cglib-repack-3.2.5.jar"和"spring-objenesis-repack-2.6.jar"是Spring框架在运行时依赖的两个关键库,它们主要涉及到动态代理和对象创建的优化。 1. **CGLIB(Code Generation Library)**: ...
activiti-spring-boot-starter-basic-6.0.0适配springboot2.1.2
这意味着你可以直接利用这些框架的模型,并通过Spring的依赖注入机制将它们注入到你的服务中。这种跨框架的兼容性使得项目可以灵活地选择最适合的AI工具,同时保持代码的整洁和可维护性。 在API设计上,Spring AI ...
spring-session+spring依赖jar包,包含spring4.0.2.RELEASE相关jar包和commons-pool2-2.4.2.jar,jedis-2.7.3.jar,spring-data-redis-1.6.2.RELEASE.jar,spring-session-1.1.1.RELEASE.jar
赠送Maven依赖信息文件:spring-web-5.3.10.pom; 包含翻译后的API文档:spring-web-5.3.10-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework:spring-web:5.3.10; 标签:springframework、...
spring-oauth-client依赖于spring-oauth-server或MyOIDC, 是OAuth2客户端演示项目。
1. **spring-security-oauth2-2.0.3.RELEASE-javadoc.jar**:这是文档JAR文件,包含Spring Security OAuth2的API文档。通过查看这些文档,开发者可以了解各个类、接口和方法的用途,以及如何在自己的项目中使用它们...