当前位置: 首页 > news >正文

网站建设入门教程企业网站服务器跟域名都需要交钱吗

网站建设入门教程,企业网站服务器跟域名都需要交钱吗,小程序开发平台售后有保障,香河家具城网站建设目标文章目录 1. 三级缓存解决的问题场景2. 三级缓存的差异性3. 循环依赖时的处理流程4. 源码验证 1. 三级缓存解决的问题场景 循环依赖指的是在对象之间存在相互依赖关系#xff0c;形成一个闭环#xff0c;导致无法准确地完成对象的创建和初始化#xff1b;当两个或多个对象彼… 文章目录 1. 三级缓存解决的问题场景2. 三级缓存的差异性3. 循环依赖时的处理流程4. 源码验证 1. 三级缓存解决的问题场景 循环依赖指的是在对象之间存在相互依赖关系形成一个闭环导致无法准确地完成对象的创建和初始化当两个或多个对象彼此之间相互引用而这种相互引用形成一个循环时就可能出现循环依赖问题。 在早期的 Spring 版本中是可以自动解决的循环依赖的问题的 public class A {Autowiredprivate B b; }public class B {Autowiredprivate A a; }但要注意Spring 解决循环依赖是有前提条件的 第一要求互相依赖的 Bean 必须要是单例的 Bean。 这是因为对于原型范围的 Beanprototype scope每次请求都会创建一个新的 Bean 实例这样每次尝试解析循环依赖时都会产生新的 Bean 实例导致无限循环由于没有全局的、持续的单例实例的缓存来引用因此循环依赖无法得到解决。 第二依赖注入的方式不能都是构造函数注入的方式。 当使用构造函数注入时一个 Bean 的实例在构造函数被完全调用之前是不会被创建的如果 Bean A 的构造函数依赖于 Bean B而 Bean B 的构造函数又依赖于 Bean A那么就会产生一个死锁的情况因为两者都不能在对方初始化之前完成初始化。 public class C {private D d;Autowiredpublic C(D d) {this.dService dService;} }public class D {private C c;Autowiredpublic D(C c) {this.c c;} }Spring 源码中关于三级缓存的定义如下 // 一级缓存 private final MapString, Object singletonObjects new ConcurrentHashMap(256); // 二级缓存 private final MapString, Object earlySingletonObjects new HashMap(16); // 三级缓存 private final MapString, ObjectFactory? singletonFactories new HashMap(16);所以说所谓的“三级缓存”就是是指三个 Map 数据结构分别用于存储不同状态的 Bean。 2. 三级缓存的差异性 一级缓存 一级缓存保存的是已经完全初始化和实例化的 Bean 对象在程序中使用的 Bean 通常就是从这个缓存中获取的这个缓存的目的是确保 Bean 只初始化一次是单例的避免多次实例化相同的Bean对象提高性能。 二级缓存 二级缓存用来解决 Bean 创建过程中的循环依赖问题它存储的是尚未完成属性注入和初始化的“半成品”Bean 对象当 Spring容器发现两个或多个 Bean 之间存在循环依赖时也就是当一个 Bean 创建过程中需要引用另一个正在创建的 BeanSpring 将创建需要的这些未完全初始化的对象提前暴露在二级缓存中以便其他 Bean 进行引用确保它们之间的依赖能够被满足。 三级缓存 三级缓存中存储的是 ObjectFactory? 类型的代理工厂对象主要用于处理存在 AOP 时的循环依赖问题每个 Bean 都对应一个 ObjectFactory 对象通过调用该对象的 getObject 方法可以获取到早期暴露出去的 Bean在该 Bean 要被其他 Bean 引用时Spring 就会用工厂对象创建出该 Bean 的实例对象最终当该 Bean 完成构造的所有步骤后就会将该 Bean 放入到一级缓存中。 3. 循环依赖时的处理流程 当 Spring 发生循环依赖时以最开始介绍的场景为例A B 两个 Bean 相互依赖以下是完善的执行流程 遍历待创建的所有 beanName在容器启动时Spring 会遍历所有需要创建的 Bean 名称在第一次遍历到 A 时就开始获取 Bean A如果 Bean A 的实例不在一级、二级缓存中缓存中没有值Spring 会开始正常的 Bean 创建流程。Bean A 的创建Bean A 的创建过程开始然后 Spring 会检查是否 A 是单例Singleton同时 A 是否已经创建完成如果 A 是单例且尚未创建完成将 A 的 BeanFactory 存入三级缓存。处理依赖注入A 开始处理 Autowired 注解尝试注入 B 属性Spring 会在一级、二级缓存中来查找 Bean B如果找不到则开始正常创建 Bean B 的流程。Bean B 的创建Bean B 的创建过程类似于 A首先判断B是否是单例且是否已创建完成如果否B 的BeanFactory 也会被存入三级缓存。B 注入 A 属性B 开始注入 A 属性尝试从一级、二级缓存中查找 A如果在缓存中找不到 AB 会尝试从三级缓存获取 A 的 BeanFactory并通过 BeanFactory的getObject()方法获取 A 的属性此时A 被存入二级缓存同时清除三级缓存因此B 能够成功注入 A 属性B 接着执行初始化处于实例化和初始化都已完成的完全状态。B 存入一级缓存B执行addSingleton()将完全状态的 B 存入一级缓存并清空二级三级缓存。A 继续注入 B 属性A 继续注入 B 属性调用beanFactory.getBean()方法获取 B由于第六步已经将 B 存入一级缓存A 可以直接获取 B成功注入 B 属性 A 接着执行初始化得到一个完全状态的 A。A 存入一级缓存A 执行addSingleton()将完全状态的 A 存入一级缓存并清空二级缓存。 此时A 和 B 都被实例化和初始化完成解决了循环依赖的问题这个流程确保了每个Bean在需要时都能够获取到已完全初始化的依赖项。 常见疑问解答 问题一为什么在 Bean B 被注入 Bean A 之前需要将 Bean A 存入二级缓存? 主要原因是如果存在其他循环依赖需要用到 A从二级缓存中直接取出早期的 Bean A 对象会更加高效。 问题二为什么创建完 Bean 后要清空二、三级缓存? 清空是为了节省存储空间一旦 Bean 完全初始化并存储在一级缓存中其在二、三级缓存中的记录就不再需要了。 问题三三级缓存为什么不能解决构造器引起的循环依赖? 这是因为构造器引起的循环依赖发生在 Bean 的实例化阶段这个阶段比二、三级缓存处理的阶段还要早无法创建出早期的半成品对象。 问题四如果不使用三级缓存只使用二级缓存能否解决循环依赖 肯定是不能的二级缓存存储的 Bean 可能是两种类型一种是实例化阶段创建出来的对象另一种是实例化阶段创建出来的对象的代理对象是否需要代理对象取决于你的配置需要如是否添加了事务注解或自定义 AOP 切面如果放弃使用三级缓存即没有 ObjectFactory那么就需要将早期的 Bean 放入二级缓存但问题是应该将未被代理的 Bean 还是代理的 Bean 放入二级缓存这只能在属性注入阶段处理注解时才能分辨。 如果直接往二级缓存添加没有被代理的 Bean那么此时注入给其它对象的 Bean 可能跟最后完全生成的 Bean 是不一样的因为最后生成使用的是可能代理对象此时注入的是原始对象这这种情况是不允许发生的。如果直接往二级缓存添加一个代理 Bean在不确定是否要使用代理对象的情况下就有提前暴露代理对象的可能正常的代理的对象都是初始化后期调用生成的是基于后置处理器的若提早的代理就违背了 Bean 定义的生命周期。 Spring 在一个三级缓存放置一个工厂如果产生循环依赖 这个工厂的作用就是判断这个对象是否需要代理如果否则直接返回如果是则返回代理对像。 4. 源码验证 在项目中双击 Shift全局查找文件AbstractAutowireCapableBeanFactory找到 550 行左右的 doCreateBean 方法重点看一下 580 行到 600 行这20行代码就行包含了三级缓存、属性注入、初始化精华都在这20行下面在源码中给出了关键注释。 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);}// 通过BeanDefinition实例化对象if (instanceWrapper null) {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 {// 属性注入 (在这里解析Autowired注解时触发循环依赖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) {// 从缓存中获取 BeanObject earlySingletonReference getSingleton(beanName, false);if (earlySingletonReference ! null) {if (exposedObject bean) {exposedObject earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping hasDependentBean(beanName)) {String[] dependentBeans getDependentBeans(beanName);SetString 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; }从缓存中获取 Bean 的源码 protected Object getSingleton(String beanName, boolean allowEarlyReference) {// Quick check for existing instance without full singleton lockObject singletonObject this.singletonObjects.get(beanName);// 从一级缓存中获取// 如果一级缓存里没有且 Bean 正在创建中// 就从二级缓存里获取if (singletonObject null isSingletonCurrentlyInCreation(beanName)) {singletonObject this.earlySingletonObjects.get(beanName);// 二级缓存没有就从三级缓存获取一个工厂if (singletonObject null allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full sinsingletonObject this.singletonObjects.get(beanName);if (singletonObject null) {singletonObject this.earlySingletonObjects.get(beanName);if (singletonObject null) {ObjectFactory? singletonFactory this.singletonFactories.get(beanName);if (singletonFactory ! null) {// 能获取到工厂则创建 BeansingletonObject singletonFactory.getObject();// 把实例存入二级缓存this.earlySingletonObjects.put(beanName, singletonObject);// 把工厂从三级缓存移除this.singletonFactories.remove(beanName);}}}}}}return singletonObject; }总之Spring 的三级缓存机制是一个巧妙的设计它解决了在 Bean 初始化过程中可能出现的循环依赖问题对于 Spring 的用户来说这意味着更加稳定和可靠的 Bean 管理和依赖注入机制。
http://www.w-s-a.com/news/779284/

相关文章:

  • 网站seo优缺点网站建设公司咨
  • 网站设计需要会什么建设网站的目的以及意义
  • 怎么样推广自己的网站wordpress register_form
  • 网站公司建站凤翔网站建设
  • 网站建设协低价格的网站建设公司
  • 研发网站建设报价深圳网站建设前十名
  • 宠物发布网站模板wordpress中文免费电商模板
  • 济南做网站创意服装品牌策划公司
  • 本地电脑做视频网站 外网连接不上软件商城源码
  • 足球直播网站怎么做crm系统介绍
  • 株洲网站建设联系方式东莞凤岗网站制作
  • 小纯洁网站开发如何注册域名
  • 网上做试卷的网站如何把刚做的网站被百度抓取到
  • 滕州网站建wordpress用户中心按钮不弹出
  • 清远新闻最新消息福建seo搜索引擎优化
  • 凡客建站网微信网站怎么做的
  • 网站建设费怎么写会计科目行业网站建设公司
  • 网站里的友情链接网站建设个人简历的网页
  • 佛山自助建站软件湖南seo优化推荐
  • 免费微信微网站模板下载不了优化人员配置
  • wordpress 导航网站主题画流程图的网站
  • 皮卡剧网站怎样做排名网
  • 网站开发 兼职哪个网站是做安全教育
  • 商品展示类网站怎么用群晖nas做网站
  • 长腿蜘蛛wordpresssem优化推广
  • 中国铁路建设监理协会官方网站深圳福田区怎么样
  • 互联网网站开发发展wordpress文章自定义栏目
  • 众筹网站平台建设工信部网站备案系统
  • 网站301重定向代码wordpress 加子目录
  • 淄博网站制作优化推广asp做学生信息网站