前言
Spring 中使用了三级缓存的设计,来解决单例模式下的属性循环依赖问题。
这句话有两点需要注意
解决问题的方法是「三级缓存的设计」
解决的只是单例模式下的 Bean 属性循环依赖问题,对于多例 Bean 和 Prototype 作用域的 Bean的循环依赖问题,并不能使用三级缓存设计解决。
Bean 的生命周期
Spring Bean 的生命周期可以简单概括为 4 个阶段
实例化(Instantiation)
属性赋值(Populate)
初始化(Initialization)
销毁(Destruction)
什么是循环依赖
public class A {
@Autowired
private B b;
}
public class B {
@Autowired
private A a;
}
如上代码所示,即 A 里面注入 B,B 里面又注入 A。此时,就发生了「循环依赖」。
三级缓存
Spring 中,单例 Bean 在创建后会被放入 IoC 容器的缓存池中,并触发 Spring 对该 Bean 的生命周期管理。
单例模式下,在第一次使用 Bean 时,会创建一个 Bean 对象,并放入 IoC 容器的缓存池中。后续再使用该 Bean 对象时,会直接从缓存池中获取。
保存单例模式 Bean 的缓存池,采用了三级缓存设计,如下代码所示。
/** Cache of singleton objects: bean name --> bean instance */
/** 一级缓存:用于存放完全初始化好的 bean **/
private final Map singletonObjects = new ConcurrentHashMap(256);
/** Cache of early singleton objects: bean name --> bean instance */
/** 二级缓存:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map earlySingletonObjects = new HashMap(16);
/** Cache of singleton factories: bean name --> ObjectFactory */
/** 三级级缓存:存放 bean 工厂对象,用于解决循环依赖 */
private final Map> singletonFactories = new HashMap>(16);
缓存层级
名称
描述
第一层缓存
singletonObjects
单例对象缓存池,存放的 Bean 已经实例化、属性赋值、完全初始化好(成品)
第二层缓存
earlySingletonObjects
早期单例对象缓存池,存放的 Bean 已经实例化但尚未属性赋值、未执行 init
方法(半成品)
第三层缓存
singletonFactories
单例工厂的缓存
使用三级缓存解决循环依赖
getSingleton方法中三级缓存的使用
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Spring首先从singletonObjects(一级缓存)中尝试获取
Object singletonObject = this.singletonObjects.get(beanName);
// 若是获取不到而且对象在建立中,则尝试从earlySingletonObjects(二级缓存)中获取
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) {
//若是仍是获取不到而且允许从singletonFactories经过getObject获取,则经过singletonFactory.getObject()(三级缓存)获取
singletonObject = singletonFactory.getObject();
//若是获取到了则将singletonObject放入到earlySingletonObjects,也就是将三级缓存提高到二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
getSingleton()
方法中
isSingletonCurrentlyInCreation()
方法用于判断当前单例 Bean 是否正在创建中,即「还没有执行初始化方法」。比如,A 的构造器依赖了 B 对象因此要先去创建 B 对象,或者在 A 的属性装配过程中依赖了 B 对象因此要先创建 B 对象,这时 A 就是处于创建中的状态。
allowEarlyReference
变量表示是否允许从三级缓存 singletonFactories
中经过 singletonFactory
的 getObject()
方法获取 Bean 对象。
分析 getSingleton()
的整个过程,可知三级缓存的使用过程如下
Spring 会先从一级缓存 singletonObjects
中尝试获取 Bean。
若是获取不到,而且对象正在建立中,就会尝试从二级缓存 earlySingletonObjects
中获取 Bean。
若还是获取不到,且允许从三级缓存 singletonFactories
中经过 singletonFactory
的 getObject()
方法获取 Bean 对象,就会尝试从三级缓存 singletonFactories
中获取 Bean。
若是在三级缓存中获取到了 Bean,会将该 Bean 存放到二级缓存中。
第三级缓存为什么可以解决循环依赖
Spring 解决循环依赖的诀窍就在于 singletonFactories
这个三级缓存。 三级缓存中使用到了ObjectFactory
接口,定义如下
public interface ObjectFactory {
T getObject() throws BeansException;
}
在 Bean 建立过程当中,有两处比较重要的匿名内部类实现了该接口。一处是 Spring 利用其建立 Bean 的时候,另外一处就是在 addSingletonFactory
方法中,如下代码所示。
addSingletonFactory(beanName, new ObjectFactory() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
此处就是解决循环依赖的关键,这段代码发生在 createBeanInstance
以后
此时,单例 Bean 对象已经实例化(可以通过对象引用定位到堆中的对象),但尚未属性赋值和初始化。
Spring 会将该状态下的 Bean 存放到三级缓存中,提早曝光给 IoC 容器(“提早”指的是不必等对象完成属性赋值和初始化后再交给 IoC 容器)。也就是说,可以在三级缓存 singletonFactories
中找到该状态下的 Bean 对象。
解决循环依赖示例分析
public class A {
@Autowired
private B b;
}
public class B {
@Autowired
private A a;
}
在上文章节铺垫的基础上,此处结合一个循环依赖的案例,分析下如何使用三级缓存解决单例 Bean 的循环依赖。
创建对象 A,完成生命周期的第一步,即实例化(Instantiation),在调用 createBeanInstance
方法后,会调用 addSingletonFactory
方法,将已实例化但未属性赋值未初始化的对象 A 放入三级缓存 singletonFactories
中。即将对象 A 提早曝光给 IoC 容器。
继续,执行对象 A 生命周期的第二步,即属性赋值(Populate)。此时,发现对象 A 依赖对象,所以就会尝试去获取对象 B。
继续,发现 B 尚未创建,所以会执行创建对象 B 的过程。
在创建对象 B 的过程中,执行实例化(Instantiation)和属性赋值(Populate)操作。此时发现,对象 B 依赖对象 A。
继续,尝试在缓存中查找对象 A。先查找一级缓存,发现一级缓存中没有对象 A(因为对象 A 还未初始化完成);转而查找二级缓存,二级缓存中也没有对象 A(因为对象 A 还未属性赋值);转而查找三级缓存 singletonFactories
,对象 B 可以通过 ObjectFactory.getObject
拿到对象 A。
继续,对象 B 在获取到对象 A 后,继续执行属性赋值(Populate)和初始化(Initialization)操作。对象 B 完成初始化操作后,会被存放到一级缓存中。
继续,转到「对象 A 执行属性赋值过程并发现依赖了对象 B」的场景。此时,对象 A 可以从一级缓存中获取到对象 B,所以可以顺利执行属性赋值操作。
继续,对象 A 执行初始化(Initialization)操作,完成后,会被存放到一级缓存中。
Spring为何不能解决非单例Bean的循环依赖
Spring 为何不能解决非单例 Bean 的循环依赖?这个问题可以细分为下面几个问题
Spring 为什么不能解决构造器的循环依赖?
Spring 为什么不能解决 prototype
作用域循环依赖?
Spring 为什么不能解决多例的循环依赖?
Spring 为什么不能解决构造器的循环依赖
对象的构造函数是在实例化阶段调用的。
上文中提到,在对象已实例化后,会将对象存入三级缓存中。在调用对象的构造函数时,对象还未完成初始化,所以也就无法将对象存放到三级缓存中。
在构造函数注入中,对象 A 需要在对象 B 的构造函数中完成初始化,对象 B 也需要在对象 A的构造函数中完成初始化。此时两个对象都不在三级缓存中,最终结果就是两个 Bean 都无法完成初始化,无法解决循环依赖问题。
Spring 为什么不能解决prototype作用域循环依赖
Spring IoC 容器只会管理单例 Bean 的生命周期,并将单例 Bean 存放到缓存池中(三级缓存)。Spring 并不会管理 prototype
作用域的 Bean,也不会缓存该作用域的 Bean,而 Spring 中循环依赖的解决正是通过缓存来实现的。
Spring 为什么不能解决多例的循环依赖
多实例 Bean 是每次调用 getBean
都会创建一个新的 Bean 对象,该 Bean 对象并不能缓存。而 Spring 中循环依赖的解决正是通过缓存来实现的。
非单例Bean的循环依赖如何解决
为什么一定要三级缓存
为什么一定要三级缓存,使用两级缓存可以解决循环依赖吗?
带着这个思考,进入下文。
尝试使用两级缓存解决依赖冲突
第三级缓存的目的是为了延迟代理对象的创建,因为如果没有依赖循环的话,那么就不需要为其提前创建代理,可以将它延迟到初始化完成之后再创建。
既然目的只是延迟的话,那么我们是不是可以不延迟创建,而是在实例化完成之后,就为其创建代理对象,这样我们就不需要第三级缓存了。因此,我们可以将 addSingletonFactory()
方法进行改造。
protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
// 判断一级缓存中不存在此对象
if (!this.singletonObjects.containsKey(beanName)) {
// 直接从工厂中获取 Bean
Object o = singletonFactory.getObject();
// 添加至二级缓存中
this.earlySingletonObjects.put(beanName, o);
this.registeredSingletons.add(beanName);
}
}
}
这样的话,每次实例化完 Bean 之后就直接去创建代理对象,并添加到二级缓存中。
测试结果是完全正常的,Spring 的初始化时间应该也是不会有太大的影响,因为如果 Bean 本身不需要代理的话,是直接返回原始 Bean 的,并不需要走复杂的创建代理 Bean 的流程。
三级缓存的意义
测试证明,二级缓存也是可以解决循环依赖的。为什么 Spring 不选择二级缓存,而要额外多添加一层缓存,使用三级缓存呢?
如果 Spring 选择二级缓存来解决循环依赖的话,那么就意味着所有 Bean 都需要在实例化完成之后就立马为其创建代理,而 Spring 的设计原则是在 Bean 初始化完成之后才为其创建代理。
使用三级缓存而非二级缓存并不是因为只有三级缓存才能解决循环引用问题,其实二级缓存同样也能很好解决循环引用问题。使用三级而非二级缓存并非出于 IOC 的考虑,而是出于 AOP 的考虑,即若使用二级缓存,在 AOP 情形注入到其他 Bean的,不是最终的代理对象,而是原始对象。
你可能感兴趣的:(面试,spring,java,后端,spring面试题,循环依赖)
JavaScript深浅拷贝原理与应用场景
痞子世无双
javascript 前端
在JavaScript中,深拷贝和浅拷贝是处理对象和数组复制的两种不同方式,理解它们的原理对于避免潜在的bug非常重要。浅拷贝(ShallowCopy)浅拷贝只复制对象或数组的第一层属性,如果属性是基本类型(如number、string、boolean等),则直接复制值;如果属性是引用类型(如object、array等),则复制引用(即内存地址),而不是实际的对象或数组。浅拷贝的实现方式使用Obj
基于HarmonyNext的ArkTS实战案例:构建高效的图像处理应用
前端
前言HarmonyNext是鸿蒙操作系统的最新版本,提供了强大的图形处理能力与高效的开发工具。ArkTS作为HarmonyNext的推荐开发语言,结合了TypeScript的静态类型检查与JavaScript的灵活性,非常适合开发高性能的图像处理应用。本文将通过实战案例,深入讲解如何基于ArkTS开发一个高性能的图像处理应用,涵盖图像加载、滤镜处理、性能优化等内容,帮助开发者快速掌握Harmony
一文轻松拿下HarmonyOS NEXT的自定义组件
harmonyos-next
程序员Feri一名12年+的程序员,做过开发带过团队创过业,擅长Java、嵌入式、鸿蒙、人工智能等,专注于程序员成长那点儿事,希望在成长的路上有你相伴!君志所向,一往无前!1.自定义组件基础在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。相比于之前学习的轻量级UI复用机制@Builder,自定义组件的功能更为强大,日常开发中如果要进行UI或业务逻
HarmonyNext 实战:基于 ArkTS 的跨设备文件加密与共享系统开发指南
前端
前言HarmonyNext是鸿蒙操作系统的最新版本,提供了强大的分布式能力与安全机制。ArkTS作为HarmonyNext的推荐开发语言,结合了TypeScript的静态类型检查与JavaScript的灵活性,非常适合开发安全性和分布式能力要求高的应用。本文将通过实战案例,深入讲解如何基于ArkTS开发一个跨设备文件加密与共享系统,涵盖文件加密、分布式传输、权限控制等内容,帮助开发者快速掌握Har
通过java下载B站视频
KeepeVile
Java
本项目分为以下几点获取Bvid获取Cid获取视频原始链接使用Java下载视频文件1.获取Bvid我们首先需要获取Bvid,也就是视频id,如果只想下载一个指定的视频那么直接输入Bvid即可。如果需要批量下载那么就需要程序帮我们抓取Bvid,关于如何使用爬虫爬取我们需要的信息,可以参考我的另一篇文章:通过Java爬虫实现51job申请职位的第四部分获取Bvid2.获取Cid这里我们需要用到一条api
Mac 利用Homebrew安装JDK
夏天的味道٥
其他 macos java 开发语言 jdk
一、安装JDK171.安装openjdk172.把homebrew安装的openjdk17软链接到系统目录:brewinstallopenjdk@17sudoln-sfn$(brew--prefix)/opt/openjdk@17/libexec/openjdk.jdk/Library/Java/JavaVirtualMachines/openjdk-17.jdk一、检查是否安装成功在Termin
Java虚拟机书单参考
阿立聊全栈
java 开发语言
关于Java虚拟机(JVM)的书籍推荐,以下是一些经典和实用的选择,涵盖从基础原理到高级调优的内容:一、中文经典书籍《深入理解Java虚拟机(第3版)》-周志明推荐理由:国内JVM领域的权威书籍,内容系统全面,涵盖JVM内存模型、垃圾回收、性能调优、字节码执行等核心知识,第3版新增了JDK11+的新特性(如ZGC、EpsilonGC)。适合人群:所有Java开发者,尤其适合需要深入JVM底层原理的
Java中的异常处理方法
后端java
必不可少的一部分。良好的异常处理机制可以提高代码的可读性、可靠性,保证程序的稳定性。本文将深度剖析Java中的异常处理机制,并分享一些最佳实践方法,帮助您在实际项目中优雅地处理异常。一、Java异常处理简介Java异常可以分为三种类型:可检查异常(checkedexception)、运行时异常(runtimeexception)和错误(error)。以下是它们之间的关系和特点:可检查异常(chec
报错The default superclass, “jakarta.servlet.http.HttpServlet“(已经配置好tomcat)
m0_74824170
面试 学习路线 阿里巴巴 servlet http tomcat
报错报错DescriptionResourcePathLocationTypeThedefaultsuperclass,“jakarta.servlet.http.HttpServlet”,accordingtotheproject’sDynamicWebModulefacetversion(5.0),wasnotfoundontheJavaBuildPath.解决办法:根据错误信息,“默认超类`
【2025年华为OD机试】(E卷,200分)-最大社交距离 (JavaScript&Java & Python&C/C++)
妄北y
华为od javascript java python c语言
一、问题描述题目解析:会议室座位安排题目描述疫情期间需要保证一定的社交距离,公司组织开交流会议。会议室有一排共N个座位,编号分别为[0,N-1]。要求员工一个接着一个进入会议室,并且可以在任何时候离开会议室。需要满足以下规则:进入规则:每当一个员工进入时,需要坐到最大社交距离(最大化自己和其他人的距离的座位)。如果有多个这样的座位,则坐到索引最小的那个座位。离开规则:元素值为负数,表示出场。例如-
【2025年华为OD机试】 (E卷,100分) - 计算最接近的数(JavaScript&Java & Python&C/C++)
妄北y
华为od javascript java python c语言
一、问题描述题目解析:寻找最接近中位数的下标题目描述给定一个数组X和一个正整数K,请找出使表达式X[i]-X[i+1]-...-X[i+K-1]的结果最接近于数组中位数的下标i。如果有多个i满足条件,请返回最大的i。补充说明数组X的元素均为正整数。数组的长度n取值范围:2{//移除输入字符串中的方括号input_str=input_str.replace("[","").replace("]","
深入理解 Promise 和 Async/Await,并结合 Axios 实践
黑风风
前端Vue学习 前端 javascript 开发语言
深入理解Promise和Async/Await,并结合Axios实践JavaScript是一门单线程的语言,这意味着它无法同时处理多个任务。然而,在实际开发中,我们经常需要处理异步操作,比如网络请求、定时器、文件读取等。为了解决这些异步操作带来的复杂性,JavaScript提供了多种方式,从最早的回调函数到现代的Promise和Async/Await,逐步让异步代码更加优雅和易于维护。本文将围绕P
基于 Spring Boot 的企业级脚手架搭建指南
一休哥助手
spring
1.引言在企业级开发中,一个良好的项目脚手架能够大大提高开发效率,统一代码规范,提升项目的可维护性。SpringBoot作为当前主流的JavaWeb开发框架,为我们提供了一个轻量级、快速启动的开发平台。本指南将详细介绍如何搭建一个适用于企业级开发的SpringBoot脚手架。2.环境准备在开始搭建之前,我们需要确保本地环境满足以下要求:JDK17及以上Maven3.6+或Gradle7+MySQL
Redis存储⑮Redis的应用_分布式锁_Lua脚本/Redlock算法
GR鲸鱼
Redis存储 分布式 redis 缓存 数据库
目录1.分布式锁的概念2.分布式锁的实现3.过期时间4.校验id5.Lua脚本6.watchdog(看门狗)7.Redlock算法8.其他功能1.分布式锁的概念在一个分布式的系统中,也会涉及到多个节点访问同一个公共资源的情况,此时就需要通过锁来做互斥控制,避免出现类似于“线程安全”的问题。而Java的synchronized或者C++的std::mutex,这样的锁都是只能在当前进程中生效,在分布
Stable Diffusion API 调用实战:详细教程
2301_79125431
java
后端开发工程师-抖音电商(24届校招)春招提前批23届试用期被裁,该怎么办日常实习offer选择:字节vs英特尔看到牛客之旅勾起的一点点“秋招总结”小鹏自驾测开二面华为光产品线华为南京数通行测图形题遇到四五次了,到底选啥呀数分实习面经合集(PayPal、爱奇艺、B站、蔚来、滴滴)联影,联通,比亚迪,军科院选哪个安慰一下被华子创到的uu们byd毁约兄弟们,面试止不住的紧张怎么办啊黑色星期五!游戏行业
什么是 Linux 内核?思维导图 代码示例(java 架构)
用心去追梦
linux java 架构
Linux内核是Linux操作系统的核心部分,它负责管理系统资源和提供硬件与软件之间的接口。内核管理诸如进程调度、内存管理、文件系统操作以及网络通信等功能,并确保这些服务能够高效且安全地运行。以下是关于Linux内核的一些关键概念:Linux内核的关键特性进程管理调度器:决定哪个进程在什么时候使用CPU。进程隔离:保证每个进程有独立的地址空间,防止相互干扰。内存管理分配和回收内存。支持虚拟内存,包
Vue 组件的三大组成部分
今天你慧了码码码码码码码码码码
Vue vue.js 前端 javascript
Vue组件通常由三大组成部分构成:模板(Template)、脚本(Script)、样式(Style)模板部分是组件的HTML结构,它定义了组件的外观和布局。Vue使用基于HTML的模板语法来声明组件的模板,可以插入动态数据、绑定事件等。脚本部分包含了组件的JavaScript代码,用于定义组件的行为逻辑。在脚本中,可以定义组件的数据(data)、计算属性(computed)、方法(methods)
为什么 Map 不能直接使用 iterator()?深入理解 Java 中 Map 的遍历方式
今天你慧了码码码码码码码码码码
JavaSE基础 java 开发语言
在Java编程中,Map是一个非常重要的数据结构,用于存储键值对(Key-Value)。然而,很多初学者在使用Map时会遇到一个问题:为什么不能直接调用map.iterator()来遍历Map呢?这篇文章将深入探讨这个问题,并介绍Map的正确遍历方式。1.Map的结构与Collection的区别Map是Java中的一个接口,常见的实现类有HashMap、TreeMap等。它的特点是存储键值对,每个
Postman接口测试的高频面试题
lucky rainbow2024
测试 面试
接口测试面试题及参考答案,轻松拿捏面试官-CSDN博客客户端与服务器端交互原理(HTTP数据请求与HTTP响应)_客户端与服务端数据交互-CSDN博客Cookie和Session的区别(面试必备)_cookie和session的作用和区别-CSDN博客
Java面试题:JDK 和 JRE 和 JVM 分别是什么,有什么区别?
神说要有光,.
java jvm 面试
官⽅解析1.JDK(JavaDevelopmentKit):JDK是Java开发⼯具包,包含了编写、编译、调试和运⾏Java程序所需的所有⼯具和组件,⽐如编译器(javac)、JavaAPI、调试⼯具等。JDK是针对Java开发⼈员的,它包含了JRE,还有编译器和其他⼯具,可以⽤来编写和调试Java程序。2.JRE(JavaRuntimeEnvironment):JRE是Java运⾏时环境,包括了
四、Springboot连接mongodb
童懵
MongoDB mongodb spring boot java
Springboot连接mongodb博客Springboot连接mongodb,mongodb是一个非关系型数据库,文档型数据库,存储的内容是JSON格式的文档,文档中可以包含各种类型的数据。Springboot连接mongodb需要引入mongoDB的驱动依赖,在pom.xml中添加:org.springframework.bootspring-boot-starter-data-mongod
数据库中的datatime的长度怎么设定_MySQL数据库面试题(2020最新版)
weixin_39765625
数据库基础知识为什么要使用数据库?数据保存在内存优点:存取速度快缺点:数据不能永久保存数据保存在文件优点:数据永久保存缺点:1)速度比内存操作慢,频繁的IO操作。2)查询数据不方便数据保存在数据库1)数据永久保存2)使用SQL语句,查询方便效率高。3)管理数据方便什么是SQL?结构化查询语言(StructuredQueryLanguage)简称SQL,是一种数据库查询语言。作用:用于存取数据、查询
探索SpringBoot自动配置的原理与案例源代码解析
程序员总部
java java 开发语言
说到SpringBoot,很多开发者都会被它的自动配置功能吸引。这个特性让我们在构建应用程序时省去了许多繁琐的配置步骤,真的是一个巨大的便利!那么,SpringBoot的自动配置到底是如何工作的呢?本文将带你深入了解其中的原理,并通过源代码的实例来解释具体是怎样实现的。自动配置的基础在SpringBoot中,自动配置依赖于一个名为@EnableAutoConfiguration的注解。这个注解的作
SpringBoot项目启动打包报错如何解决类文件版本不匹配?
程序员总部
java intellij-idea maven java
在使用SpringBoot进行项目开发时,可能会遇到一个常见的错误:在启动或打包的时候,系统提示“类文件具有错误的版本61.0,应为52.0”。这个错误通常跟Java的版本有关,尤其是在不同版本的Java之间转移时。接下来,我们就来聊聊这个问题的成因以及如何解决它。**什么是类文件版本呢?**Java编译器在编译Java源代码的时候,会生成.class文件,这些文件在不同版本的Java中对应着不同
【springboot集成knife4j】
龙少9543
后端 spring boot java 后端
SpringBoot集成knife4jKnife4j是为JavaMVC框架集成Swagger生成API文档的一套增强解决方案,它基于Swagger原有的基础上进行了一些改进和增强,提供了更简洁的UI界面,同时支持更多的自用化配置。下面是在SpringBoot项目中集成Knife4j的基本步骤:1.引入依赖首先,在你的pom.xml文件中添加Knife4j的相关依赖。确保你已经使用了SpringBo
24、《Spring Boot 的 Actuator 监控深度解析》
wolf犭良
SpringBoot spring boot 后端 java
SpringBoot的Actuator监控深度解析引言在微服务架构盛行的今天,应用监控已成为保障系统可靠性的关键环节。SpringBootActuator作为官方提供的监控解决方案,通过暴露丰富的端点(Endpoints)帮助开发者实时掌握应用运行时状态。本文将深入剖析Actuator的核心机制,从基础配置到高级定制,结合实战代码演示如何构建完整的监控体系。一、Actuator核心机制解析1.1A
1、JDK JRE JVM 面试问了
好运天天有,向我滚滚来
技术面试——一二阶段 java
目录一、JDKJREJVM的区别(必会)二、JDKJDK的安装配置JDK1.8的新特性(高薪常问)JVMjava跨平台JVM机制--jvm/java类加载器/加载类class文件/类加载的实现—面试JVM运行时内存(高薪)JVM内存中的两大对象java中会存在内存泄漏吗,请简单描述。JVM算法(GC-jvm垃圾回收算法/是一个守护线程)简单说说GC如何请求垃圾收集如何发现垃圾/发现垃圾的算法如何回
《2025软件测试工程师面试》接口框架TestNg篇
悠然的笔记本
面试 职场和发展
TestNG面试题TestNG代表”测试下一代”。它是Credricbeust开发的用于Java编程语言的自动化测试框架,它是从JUnit框架得到启发而来的。TestNG包含JUnit框架的所有功能,但还包含一些其他功能,这些功能使TestNG更加强大。Testng框架的特点支持测试方法的依赖、灵活的测试配置、丰富的注解支持等适用于需要
Java面试基础问题之(一)—— JDK和JRE区别
ProLayman
Java基础问题 JDK和JRE区别
JDK:JavaDevelopmentKitJava开发包JRE:JavaRuntimeEnvironmentJava运行环境从名字就能看出,JRE是JDK的子集,举个通俗的例子,如果只是想运行.class文件,JRE就够了。但是要想编写运行.java文件,就得要JDK。具体JDK和JRE在组成上的区别可以见下图:Java技术体系图:除了JRE之外,JDK还提供了Java编译器(javac),开发
腾讯集团软件开发-后台开发方向内推
飞300
业界资讯 mysql java
熟练掌握C/C++/Java/Go等其中一门开发语言;TCP/UDP网络协议及相关编程、进程间通讯编程;专业软件知识,包括算法、操作系统、软件工程、设计模式、数据结构、数据库系统、网络安全等有一定了解的:1、Python、Shell、Perl等脚本语言;2、MySQL及SQL语言、编程;3、NoSQL,Key-value存储原理。1、深入理解业务需求和产品设计,高效地实现并优化产品功能;2、持续优
java线程Thread和Runnable区别和联系
zx_code
java jvm thread 多线程 Runnable
我们都晓得java实现线程2种方式,一个是继承Thread,另一个是实现Runnable。
模拟窗口买票,第一例子继承thread,代码如下
package thread;
public class ThreadTest {
public static void main(String[] args) {
Thread1 t1 = new Thread1(
【转】JSON与XML的区别比较
丁_新
json xml
1.定义介绍
(1).XML定义
扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML使用DTD(document type definition)文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准。
XML是标
c++ 实现五种基础的排序算法
CrazyMizzz
C++ c 算法
#include<iostream>
using namespace std;
//辅助函数,交换两数之值
template<class T>
void mySwap(T &x, T &y){
T temp = x;
x = y;
y = temp;
}
const int size = 10;
//一、用直接插入排
我的软件
麦田的设计者
我的软件 音乐类 娱乐 放松
这是我写的一款app软件,耗时三个月,是一个根据央视节目开门大吉改变的,提供音调,猜歌曲名。1、手机拥有者在android手机市场下载本APP,同意权限,安装到手机上。2、游客初次进入时会有引导页面提醒用户注册。(同时软件自动播放背景音乐)。3、用户登录到主页后,会有五个模块。a、点击不胫而走,用户得到开门大吉首页部分新闻,点击进入有新闻详情。b、
linux awk命令详解
被触发
linux awk
awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息
awk处理过程: 依次对每一行进行处理,然后输出
awk命令形式:
awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file
[-F|-f|-v]大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=val
各种语言比较
_wy_
编程语言
Java Ruby PHP 擅长领域
oracle 中数据类型为clob的编辑
知了ing
oracle clob
public void updateKpiStatus(String kpiStatus,String taskId){
Connection dbc=null;
Statement stmt=null;
PreparedStatement ps=null;
try {
dbc = new DBConn().getNewConnection();
//stmt = db
分布式服务框架 Zookeeper -- 管理分布式环境中的数据
矮蛋蛋
zookeeper
原文地址:
http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
安装和配置详解
本文介绍的 Zookeeper 是以 3.2.2 这个稳定版本为基础,最新的版本可以通过官网 http://hadoop.apache.org/zookeeper/来获取,Zookeeper 的安装非常简单,下面将从单机模式和集群模式两
tomcat数据源
alafqq
tomcat
数据库
JNDI(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API。
没有使用JNDI时我用要这样连接数据库:
03. Class.forName("com.mysql.jdbc.Driver");
04. conn
遍历的方法
百合不是茶
遍历
遍历
在java的泛
linux查看硬件信息的命令
bijian1013
linux
linux查看硬件信息的命令
一.查看CPU:
cat /proc/cpuinfo
二.查看内存:
free
三.查看硬盘:
df
linux下查看硬件信息
1、lspci 列出所有PCI 设备;
lspci - list all PCI devices:列出机器中的PCI设备(声卡、显卡、Modem、网卡、USB、主板集成设备也能
java常见的ClassNotFoundException
bijian1013
java
1.java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory 添加包common-logging.jar2.java.lang.ClassNotFoundException: javax.transaction.Synchronization
【Gson五】日期对象的序列化和反序列化
bit1129
反序列化
对日期类型的数据进行序列化和反序列化时,需要考虑如下问题:
1. 序列化时,Date对象序列化的字符串日期格式如何
2. 反序列化时,把日期字符串序列化为Date对象,也需要考虑日期格式问题
3. Date A -> str -> Date B,A和B对象是否equals
默认序列化和反序列化
import com
【Spark八十六】Spark Streaming之DStream vs. InputDStream
bit1129
Stream
1. DStream的类说明文档:
/**
* A Discretized Stream (DStream), the basic abstraction in Spark Streaming, is a continuous
* sequence of RDDs (of the same type) representing a continuous st
通过nginx获取header信息
ronin47
nginx header
1. 提取整个的Cookies内容到一个变量,然后可以在需要时引用,比如记录到日志里面,
if ( $http_cookie ~* "(.*)$") {
set $all_cookie $1;
}
变量$all_cookie就获得了cookie的值,可以用于运算了
java-65.输入数字n,按顺序输出从1最大的n位10进制数。比如输入3,则输出1、2、3一直到最大的3位数即999
bylijinnan
java
参考了网上的http://blog.csdn.net/peasking_dd/article/details/6342984
写了个java版的:
public class Print_1_To_NDigit {
/**
* Q65.输入数字n,按顺序输出从1最大的n位10进制数。比如输入3,则输出1、2、3一直到最大的3位数即999
* 1.使用字符串
Netty源码学习-ReplayingDecoder
bylijinnan
java netty
ReplayingDecoder是FrameDecoder的子类,不熟悉FrameDecoder的,可以先看看
http://bylijinnan.iteye.com/blog/1982618
API说,ReplayingDecoder简化了操作,比如:
FrameDecoder在decode时,需要判断数据是否接收完全:
public class IntegerH
js特殊字符过滤
cngolon
js特殊字符 js特殊字符过滤
1.js中用正则表达式 过滤特殊字符, 校验所有输入域是否含有特殊符号function stripscript(s) { var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]"
hibernate使用sql查询
ctrain
Hibernate
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.hibernate.Hibernate;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transa
linux shell脚本中切换用户执行命令方法
daizj
linux shell 命令 切换用户
经常在写shell脚本时,会碰到要以另外一个用户来执行相关命令,其方法简单记下:
1、执行单个命令:su - user -c "command"
如:下面命令是以test用户在/data目录下创建test123目录
[root@slave19 /data]# su - test -c "mkdir /data/test123"
好的代码里只要一个 return 语句
dcj3sjt126com
return
别再这样写了:public boolean foo() { if (true) { return true; } else { return false;
Android动画效果学习
dcj3sjt126com
android
1、透明动画效果
方法一:代码实现
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_main, container, fals
linux复习笔记之bash shell (4)管道命令
eksliang
linux管道命令汇总 linux管道命令 linux常用管道命令
转载请出自出处:
http://eksliang.iteye.com/blog/2105461
bash命令执行的完毕以后,通常这个命令都会有返回结果,怎么对这个返回的结果做一些操作呢?那就得用管道命令‘|’。
上面那段话,简单说了下管道命令的作用,那什么事管道命令呢?
答:非常的经典的一句话,记住了,何为管
Android系统中自定义按键的短按、双击、长按事件
gqdy365
android
在项目中碰到这样的问题:
由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成:
1、单击事件:就是普通key的单击;
2、双击事件:500ms内同一按键单击两次;
3、长按事件:同一按键长按超过1000ms(系统中长按事件为500ms);
4、组合按键:两个以上按键同时按住;
asp.net获取站点根目录下子目录的名称
hvt
.net C# asp.net hovertree Web Forms
使用Visual Studio建立一个.aspx文件(Web Forms),例如hovertree.aspx,在页面上加入一个ListBox代码如下:
<asp:ListBox runat="server" ID="lbKeleyiFolder" />
那么在页面上显示根目录子文件夹的代码如下:
string[] m_sub
Eclipse程序员要掌握的常用快捷键
justjavac
java eclipse 快捷键 ide
判断一个人的编程水平,就看他用键盘多,还是鼠标多。用键盘一是为了输入代码(当然了,也包括注释),再有就是熟练使用快捷键。 曾有人在豆瓣评
《卓有成效的程序员》:“人有多大懒,才有多大闲”。之前我整理了一个
程序员图书列表,目的也就是通过读书,让程序员变懒。 写道 程序员作为特殊的群体,有的人可以这么懒,懒到事情都交给机器去做,而有的人又可
c++编程随记
lx.asymmetric
C++ 笔记
为了字体更好看,改变了格式……
&&运算符:
#include<iostream>
using namespace std;
int main(){
int a=-1,b=4,k;
k=(++a<0)&&!(b--
linux标准IO缓冲机制研究
音频数据
linux
一、什么是缓存I/O(Buffered I/O)缓存I/O又被称作标准I/O,大多数文件系统默认I/O操作都是缓存I/O。在Linux的缓存I/O机制中,操作系统会将I/O的数据缓存在文件系统的页缓存(page cache)中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。1.缓存I/O有以下优点:A.缓存I/O使用了操作系统内核缓冲区,
随想 生活
暗黑小菠萝
生活
其实账户之前就申请了,但是决定要自己更新一些东西看也是最近。从毕业到现在已经一年了。没有进步是假的,但是有多大的进步可能只有我自己知道。
毕业的时候班里12个女生,真正最后做到软件开发的只要两个包括我,PS:我不是说测试不好。当时因为考研完全放弃找工作,考研失败,我想这只是我的借口。那个时候才想到为什么大学的时候不能好好的学习技术,增强自己的实战能力,以至于后来找工作比较费劲。我
我认为POJO是一个错误的概念
windshome
java POJO 编程 J2EE 设计
这篇内容其实没有经过太多的深思熟虑,只是个人一时的感觉。从个人风格上来讲,我倾向简单质朴的设计开发理念;从方法论上,我更加倾向自顶向下的设计;从做事情的目标上来看,我追求质量优先,更愿意使用较为保守和稳妥的理念和方法。
&