专题系列分类:玩转SpringBoot2.x系列教程
1 demo 版本说明
开发工具: Spring Tool Suite (STS)
springboot版本: 2.0.5.RELEASE
jdk版本: 1.8.0_144
在阅读该博客前建议大家一定要把demo写下来 在自己的环境下,根据操作静下心来一步步看。阅读源码本身是一个比较费神的操作,建议大家一定要多看 看明白后自己在把大体思路捋一下。 因为springboot用的也是spirng 所以下面介绍主要是spirng 而不是springboot 特此说明。
2 通过BeanPostProcessor 进行Bean 初始化回调前后进行自定义操作
我们知道spring可以为我们创建bean对象实例 和以及Bean 属性注入,但是如果我们想要在Bean自动装配完成后自定义操作怎么处理呢?我们需要BeanPostProcessor 接口来完成自定义操作处理。当你还不知道我在说什么的情况下,那就直接看下面的代码吧。
定义一个名称为IMyBean的接口其中有2个方法 一个获取自定义值getCustomValue 一个进行设置自定义值的方法 setCustomValue
package cn.lijunkui.customBean;
public interface IMyBean {
void setCustomValue(String v);
String getCustomValue();
}
创建名称为MyBean的实体类 并实现IMyBean 并通过@Component 直接声明该类为spirng的bean
package cn.lijunkui.customBean;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements IMyBean{
private String customValue;
@Override
public void setCustomValue(String customValue) {
this.customValue = customValue;
}
@Override
public String getCustomValue() {
return customValue;
}
}
创建实现BeanPostProcessor 的实现类完成对MyBean的初始化后自定义操作 如果在初始化MyBean 后customValue的值如果为空则将其设置为“defaultValue”
package cn.lijunkui.customBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
private Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof IMyBean) {
log.info("=======>postProcessAfterInitialization");
IMyBean mybean = (IMyBean) bean;
if (mybean.getCustomValue() == null) {
mybean.setCustomValue("defaultValue");
}
}
return bean;
}
}
通过在启动类中获取ConfigurableApplicationContext 获取MyBean测试customValue的值是否改变。(这里我们额外说一下Spirng中的bean都是通过BeanFactory进行管理的,在Spirng中默认使用的是DefaultListableBeanFactory 也就是BeanFactory的实现。 而下面代码中ConfigurableApplicationContext getBean 就是BeanFactory中的方法)
package cn.lijunkui;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import cn.lijunkui.customBean.MyBean;
@SpringBootApplication
public class PrincipleApplication {
private static Logger log=LoggerFactory.getLogger(PrincipleApplication.class);
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(PrincipleApplication.class, args);
MyBean mybean = run.getBean(MyBean.class);
log.info("getCustomValue:"+mybean.getCustomValue());
}
}
测试结果: 我们看到下图中加载的过程中进行了回调并且将customValue的值设置成了 defaultValue
为什么实现 BeanPostProcessor就可以进行bean初始化后的操作呢?想知道其中的原理我们就要去看看spring的源码了。
第一步在MyBeanPostProcessor postProcessAfterInitialization方法中打一个段断点 然后启动spirngboot项目
当断点走到 postProcessAfterInitialization 方法上事 如下图它的调用链就出来了,是不是很清晰。
根据上图调用链我们继续查看 AbstractAutowireCapableBeanFactory.initializeBean 方法 该方法中我们看到和BeanPostProcessor 有关的2个方法
applyBeanPostProcessorsBeforeInitialization 和applyBeanPostProcessorsBeforeInitialization 是不是感觉和BeanPostProcessor 相关,下面是initializeBean 具体逻辑实现
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* Called from {@link #createBean} for traditionally defined beans,
* and from {@link #initializeBean} for existing bean instances.
* @param beanName the bean name in the factory (for debugging purposes)
* @param bean the new bean instance we may need to initialize
* @param mbd the bean definition that the bean was created with
* (can also be {@code null}, if given an existing bean instance)
* @return the initialized bean instance (potentially wrapped)
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction) () -> {
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;
}
applyBeanPostProcessorsBeforeInitialization 方法的具体实现逻辑如下
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
当我们看到Object current = processor.postProcessBeforeInitialization(result, beanName); 是不是知道了 这里会获取所有的BeanPostProcessor 然后调用postProcessBeforeInitialization
BeanPostProcessors 逻辑如下:
获取AbstractBeanFactory 中的 beanPostProcessors
/**
* Return the list of BeanPostProcessors that will get applied
* to beans created with this factory.
*/
public List getBeanPostProcessors() {
return this.beanPostProcessors;
}
applyBeanPostProcessorsAfterInitialization 逻辑和applyBeanPostProcessorsBeforeInitialization 逻辑基本一直 代码如下
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
BeanPostProcessor 调用时序图如下:中间很多流程做了简化 画的是核心的逻辑。
。
还有一个问题就是我们的 BeanPostProcessor 集合是在什么时添加的?关闭到我们的springboot服务
还是下图的断点 在次一debug方式启动
通过调用的链路往下找 知道找到 AbstractApplicationContext 中的refresh() 方法中的 registerBeanPostProcessors(beanFactory)
通过PostProcessorRegistrationDelegate.registerBeanPostProcessors 将 放入到beanFactory 中
registerBeanPostProcessors 方法中获取到所有的BeanPostProcessor 然后放入集合中
然后再将BeanPostProcessor集合 放入到 beanFactory 中
PostProcessorRegistrationDelegate registerBeanPostProcessors 具体源码逻辑如下
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List priorityOrderedPostProcessors = new ArrayList<>();
List internalPostProcessors = new ArrayList<>();
List orderedPostProcessorNames = new ArrayList<>();
List nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
通过下图了解springboot启动后如何执行到 AbstractApplicationContext refresh 方法流程。
大致流程如下:
在 Spring 初始化完成后会回调 GenericApplicationContext 中的 refresh 方法,然后再通过AbstractApplicationContext 抽象类中的 refresh 来实现。
在refresh 方法中registerBeanPostProcessors 调用了 PostProcessorRegistrationDelegate,将 BeanFactory 作为参数传入,在registerBeanPostProcessors中获取所有的BeanPostProcessor获取完所有实现类后,根据实现类上的顺序进行排序,然后将排序好的集合对象调用BeanFactory.addBeanPostProcessor 注册到 BeanFactory 中。
这样在 AbstractAutowireCapableBeanFactory 中就可以从它的父类 AbstractBeanFactory 中直接获取到 BeanPostProcessor 集合对象了,也就是上面调用的 getBeanPostProcessors() 方法。
你可能感兴趣的:(【SpringBoot】,springboot,springboot原理)
征程 6 工具链 BEVPoolV2 算子使用教程 1 - BEVPoolV2 算子详解
算法自动驾驶
1.引言当前,地平线征程6工具链已经全面支持了BEVPoolingV2算子,并与mmdetection3d的实现完成了精准对齐。然而,需要注意的是,此算子因其内在的复杂性以及相关使用示例的稀缺,致使部分用户在实际运用过程中遭遇了与预期不符的诸多问题。在这样的背景下,本文首先会对BEVPoolingV2的实现进行全方位、细致入微的剖析讲解,,让复杂的原理变得清晰易懂。随后,还会通过代表性的示例,来进
2万字长文,九篇论文读懂大语言模型的前世今生
人工智能
2万字长文,九篇论文读懂大语言模型的前世今生友情提示:这是一篇2W字长文,但我保证,它绝对值得一读!如果感兴趣的话,感谢关注,点赞转发在看收藏,五键四连,谢谢~更多LLM架构文章:LLM架构专栏近日热文:1.全网最全的神经网络数学原理(代码和公式)直观解释2.大模型进化史:从Transformer到DeepSeek-R1的AI变革之路3.2W8000字深度剖析25种RAG变体:全网最全~没有之一4
深入解析/etc/hosts.allow与 /etc/hosts.deny:灵活控制 Linux 网络访问权限
XMYX-0
linux 网络 服务器
文章目录深入解析/etc/hosts.allow与/etc/hosts.deny:灵活控制Linux网络访问权限引言什么是TCPWrappers?工作原理什么是/etc/hosts.allow和/etc/hosts.deny?匹配规则配置语法详解配置示例允许特定IP访问SSH服务拒绝整个子网访问FTP服务允许内网,拒绝外网记录非法访问尝试注意事项高级配置与技巧允许特定IP地址访问服务拒绝某个网段的
MATLAB输出切换分数、小数
北冰洋漂流
MATLAB matlab 开发语言
切换分数形式显示:formatrat返回小数格式显示:formatshort或者formatdefault原理:MATLAB使用format函数控制输出时的格式官网指导文件:设置输出显示格式-MATLABformat-MathWorks中国
深入解析Vue3单文件组件:原理、场景与实战
念九_ysl
Vue vue.js 前端 javascript
一、SFC是什么?单文件组件(Single-FileComponents,SFC)是Vue的标志性特性,以.vue为扩展名的文件将模板、逻辑和样式封装在单一文件中。Vue3的SFC在保留经典设计的同时,针对现代开发需求进行了多项优化:{{count}}+1import{ref}from'vue'constcount=ref(0)constincrement=()=>count.value++.co
@Schedule定时任务+分布式环境一些踩过的坑~
架构文摘JGWZ
分布式 学习 后端
定时任务的实现方式多种多样,框架也是层出不穷。“本文所谈及的是SpringBoot本身所带有的@EnableScheduling、@Scheduled实现定时任务的方式。以及采用这种方式,在分布式调度中可能会出现的问题,又针对为什么会发生这种问题?又该如何解决,做出了一些叙述。为了适合每个阶段的读者,我把前面测试的代码都贴出来啦~确保每一步都是有迹可循的,希望大家不要嫌啰嗦,感谢一、搭建基本环境基
DeepSeek+Kimi
xjfgkf
mysql sqlite oracle json
DeepSeek与Kimi生成PPT全流程解析一、工具分工原理DeepSeek核心作用:生成结构化PPT大纲(擅长逻辑构建与内容优化)Kimi核心作用:将文本转换为视觉化PPT(提供模板库与排版引擎)二、操作步骤详解1.通过DeepSeek生成PPT大纲down输入提示词示例(需包含三要素)你是有10年经验的AI行业分析师,请为科技公司投资人制作一份30页的PPT,要求:首页包含主标题与3个核心论
132java ssm springboot基于大数据的吉林省农村产权交易数据分析可视化平台系统(源码+文档+运行视频+讲解视频)
QQ2279239102
spring boot 大数据 数据分析 开发语言 maven vue.js
文章目录系列文章目录目的前言一、详细视频演示二、项目部分实现截图三、技术栈后端框架springboot前端框架vue持久层框架MyBaitsPlus系统测试四、代码参考源码获取目的摘要:本文介绍了基于JavaSSM和SpringBoot开发的吉林省农村产权交易数据分析可视化平台系统,为农村产权交易市场提供决策支持。系统前端利用HTML、CSS和JavaScript构建直观的可视化界面,后端运用Ja
深入浅出:ASP.NET Core 中间件的使用与封装
江沉晚呤时
Net core c# 后端 架构 开发语言
在ASP.NETCore中,中间件(Middleware)是处理HTTP请求和响应的核心组件。中间件可以在请求到达最终处理前对请求进行处理,也可以在响应返回客户端之前修改响应。通过使用中间件,开发者能够灵活地扩展应用程序功能,处理认证、日志记录、跨域请求、错误处理等常见任务。本文将详细介绍ASP.NETCore中间件的工作原理、如何使用内置中间件、如何封装自定义中间件,并提供实际的例子来帮助你掌握
出现 当 IDENTITY INSERT 设置为 OF 时,不能为表‘xxx‘ 中的标识列插入显式值解决方法
码农研究僧
BUG 数据库 sqlserver IDENTITY
目录前言1.问题所示2.原理分析前言找工作,来万码优才:#小程序://万码优才/r6rqmzDaXpYkJZF1.问题所示插入数据到数据库的时候,出现如下Bug:[23000][Microsotl[ODBCDrver17forsOLsernver[sQLSerer)当IDENTITYINSERT设置为OF时,不能为表'RunningDRC'中的标识列插入显式值。(544)截图如下:2.原理分析表的
使用第三方工具监控 SpringBoot 接口超时,简单几步搞定!
程序员蜗牛g
springboot spring boot 后端 java
点击上方“程序员蜗牛g”,选择“设为星标”跟蜗牛哥一起,每天进步一点点程序员蜗牛g大厂程序员一枚跟蜗牛一起每天进步一点点31篇原创内容公众号为了实现SpringBoot项目的接口超时监控并触发邮件告警,以下是一些常用的第三方工具和解决方案,可根据项目规模和需求灵活选择。一、开源方案1.Prometheus+Alertmanager+Grafana功能特点:Prometheus:时序数据库,实时采集
使用 Spring Boot Admin 管理和监控 Spring Boot 应用程序
AI天才研究院
Python实战 自然语言处理 人工智能 语言模型 编程实践 开发语言 架构设计
作者:禅与计算机程序设计艺术1.简介SpringBoot是一款开源框架,它让初学者能够快速地开发出基于Spring框架的应用程序。在过去的一年中,SpringBoot在GitHub上持续活跃,在全球范围内取得了令人瞩目的数据,获得了大量关注。目前,SpringBoot的版本号已经从2.x发展到了2.5.x、2.6.x和2.7.x。根据GitHub上的Star数据,截至2021年9月1日,Sprin
非常哇塞的 SpringBoot性能优化长文!
肥肥技术宅
java 大数据 java
SpringBoot已经成为Java届的No.1框架,每天都在蹂躏着数百万的程序员们。当服务的压力上升,对SpringBoot服务的优化就会被提上议程。本文将详细讲解SpringBoot服务优化的一般思路,并附上若干篇辅助文章作为开胃菜。本文较长,最适合收藏之。1.有监控才有方向在开始对SpringBoot服务进行性能优化之前,我们需要做一些准备,把SpringBoot服务的一些数据暴露出来。比如
XXL-JOB完全开发手册(一篇学会XXL-JOB所有知识点)
hao_kkkkk
JAVA实战开发手册 java xxl-job
目录1、什么是XXL-JOB1.1、XXL-JOB简介1.2、XXL-JOB构成调度模块(调度中心):执行模块(执行器):任务:1.3、XXL-JOB总结编辑2、XXL-JOB原理2.1、执行器的注册和发现2.2、调度中心调用执行器调度中心的操作:执行器的操作:3、XXL-JOB能够解决哪些问题4、XXL-JOB优点特性5、XXL-JOB安装部署5.1、文档及源码5.2、调度中心部署5.2.1、初
STM32 MPU6050 六轴陀螺仪教程(HAL 库零基础入门)
与光同尘 大道至简
stm32 嵌入式硬件 单片机
本教程将详细介绍如何在STM32微控制器上使用HAL库驱动MPU6050六轴姿态传感器,适合零基础的初学者学习。内容涵盖基础知识、硬件连接、开发环境配置、驱动编写、数据处理、示例代码以及调试与优化等方面。通过本教程,读者将了解MPU6050的工作原理,掌握STM32I2C通信的使用方法,并能够读取MPU6050的加速度、角速度和温度等数据,进而进行姿态角的计算。1.基础知识MPU6050传感器工作
STM32F103C8T6 驱动 0.96 寸 OLED (SSD1306, I2C 接口) 教程
与光同尘 大道至简
stm32 嵌入式硬件 单片机
本教程详细介绍如何使用STM32F103C8T6微控制器(常见为“蓝色飞线板”BluePill)通过I2C接口驱动0.96寸OLED显示屏(SSD1306控制器),使用STM32HAL库进行开发。内容从基础知识开始,一步步带领初学者完成OLED显示从初始化到显示文字、图形和图片的完整过程。1.基础知识OLED显示屏工作原理OLED(OrganicLight-EmittingDiode,有机发光二极
嘉立创EDA常用快捷键汇总
与光同尘 大道至简
pcb工艺 课程设计 蓝桥杯 人机交互 社交电子 程序人生
以下整理了一份嘉立创EDA常用快捷键的汇总,分为共用快捷键、原理图快捷键和PCB快捷键三大类,供你参考(所有快捷键均可在软件内进行自定义修改)。共用快捷键旋转与翻转:空格键:旋转所选图形R:旋转图形X:水平翻转(封装除外)Y:垂直翻转(封装除外)平移与缩放:鼠标右键拖动:拖动画布Left/Right/Up/Down:分别向左、右、上、下滚动或移动所选图形A/Z:放大/缩小D:拖动K:适合窗口显示文
一文带你了解多租户模式
蠢死的脑细胞
框架 设计模式 数据库 springcloud
前言本文主要介绍了多租户的相关概念和实现原理,具体的实现相信你看完博客之后自己就知道怎么去写了,如果还是不了解的话,欢迎留言,博主会补充对应的代码实现。什么是多租户你们公司研发一套学生管理系统,现在将这套系统出售不同的学校,每个学校根据自己的需要选择需要的功能,如果每个学校都部署一套系统,那么将会浪费掉很多服务器资源,那么可不可以只部署一套,然后使用技术手段在物理或逻辑将不同的学校进行功能和数据隔
K-means聚类:解锁数据隐藏结构的钥匙
蓝天资源分享
kmeans 聚类 机器学习
K-means聚类:解锁数据隐藏结构的钥匙在机器学习的广阔领域中,无监督学习以其独特的魅力吸引了众多研究者和实践者。其中,K-means聚类作为一种经典且实用的无监督学习算法,以其简单高效的特点,广泛应用于市场细分、图像分割和基因聚类等领域。本文将深入探讨K-means聚类的工作原理、应用实例及其在这些领域中的具体应用,旨在揭示其如何智能划分数据,解锁隐藏结构,为相关领域提供精准导航。一、K-me
电池管理系统(BMS)架构详细解析:原理与器件选型指南
web13595609705
面试 学习路线 阿里巴巴 架构
BMS(电池管理系统)架构详细讲解从你提供的BMS(BatteryManagementSystem)架构图来看,主要涉及到电池监控模块、通信模块、功率控制模块等部分。下面我将详细讲解该架构的各个功能模块及其工作原理。1.电池管理核心模块电池管理系统的核心部分由BQ76930芯片组成(图中的两个芯片,分别对应8节和9节电池),它负责管理和监控电池组的状态,包括电压、电流、温度等数据。BQ76930:
Spring Boot如何利用Twilio Verify 发送验证码短信?
HBLOGA
Spring Boot Demo spring boot 后端 java
Twilio提供了一个名为TwilioVerify的服务,专门用于处理验证码的发送和验证。这是一个更为简化和安全的解决方案,适合需要用户身份验证的应用。使用TwilioVerify服务的步骤以下是如何在SpringBoot中集成TwilioVerify服务的步骤:1.添加依赖确保在pom.xml中添加Twilio的依赖(如果尚未添加):springboot-democom.et1.0-SNAPSH
共享模型之管程(悲观锁)
小小uzi
java 悲观锁 juc 并发
共享模型之管程(悲观锁)文章目录共享模型之管程(悲观锁)一、常见线程安全的类二、对象头三、Monitor(监视器/管程)四、偏向锁偏向锁的实现原理撤销偏向锁五、轻量级锁轻量级锁的释放六、重量级锁七、锁的升级流程八、sleep/wait/parksleepwaitpark九、多把锁相关十、ReentrantLock一、常见线程安全的类StringIntegerStringBufferRandomVe
深度解析大模型蒸馏方法:原理、差异与案例
赵大仁
AI 人工智能 大语言模型 人工智能
深度解析大模型蒸馏方法:原理、差异与案例1.引言随着深度学习的飞速发展,大模型(LargeModels)如GPT、BERT、ViT逐渐成为AI领域的主流。然而,这些模型通常参数量庞大,计算开销极高,不适用于移动端或低算力环境。因此,模型蒸馏(KnowledgeDistillation,KD)作为一种模型压缩技术,成为高效部署大模型的重要手段。在本篇文章中,我们将深入探讨不同类型的模型蒸馏方法,并通
Redis事务原理
超人在良家-阿启
redis redis 数据库 缓存
redis事务原理redis事务时基于SessionCallback实现的,因为要在一个连接里执行命令,那我们看看具体的实现,如下:redisTemplate.execute((RedisOperationsres)->{})对SessionCallback实现的是lambda表达式@ApiOperation(value="multi测试接口",notes="redis事务测试接口")@Reque
说一下redis事务底层原理
LUCIAZZZ
redis 数据库 java 缓存 网络 计算机网络 acid
Redis事务1.事务的基本流程Redis事务通过MULTI、EXEC、WATCH等命令实现,底层原理可以分为以下几个步骤:(1)MULTI命令当客户端发送MULTI命令时,Redis会将客户端标记为“事务模式”。在事务模式下,客户端发送的所有命令不会立即执行,而是被放入一个队列(命令队列)中。(2)命令入队在MULTI和EXEC之间,客户端发送的所有命令都会被追加到事务队列中。这些命令不会立即执
2025年计算机毕业设计springboot 校园二手物品交易平台的设计与实现
基林计算机毕设程序
课程设计 spring boot 后端
本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容选题背景随着环保意识的增强和校园经济的蓬勃发展,校园二手物品交易逐渐成为大学生群体中的重要经济活动。当前,国内外对于二手物品交易的研究主要集中在电商平台的发展、交易模式的创新以及市场潜力的挖掘等方面。然而,专门针对校园二手物品交易平台的研究相对较少,尤其是结合大学生实际需求和行为特点的
深入浅出:UniApp 从入门到精通全指南
大胖丫
uni-app
https://juejin.cn/post/7440119937644101684uni-app官网本文是关于UniApp从入门到精通的全指南,涵盖基础入门(环境搭建、创建项目、项目结构、编写运行)、核心概念与进阶知识(组件与开发、页面路由与导航、数据绑定与响应式原理、生命周期钩子)、电商应用开发(商品展示、购物车、订单结算等功能)、项目优化与部署(性能、安全优化及不同平台部署)、案例分析及总结
什么是情绪分析?基本指南
沃丰科技
人工智能 科技 科技 语音识别 人工智能 自然语言处理
情感分析用于了解文本中的观点、情感和态度。情绪分析也称为情绪分类或观点挖掘,允许您通过提取特定单词或短语来确定内容是正面、消极还是中性。情绪分析的主要目的是分析公众对某些产品、事件、人或想法的看法。过去几年来,该领域取得了重大进展,这主要是由于用户生成的情绪分析数据空前增长。它现在有无数的应用,为大企业、政治、心理学和社会学提供见解。本基本指南旨在概述情绪分析:基本面、各种类型的情绪分类、工作原理
基于Stm32单片机的串口通信协议
日富一日,加油
stm32 嵌入式硬件 单片机
目录一、串口介绍1、电平标准2、串口参数及时序二、串口收发功能实现1、配置串口原理2、代码实现三、串口数据包发送1、状态机2、代码实现一、串口介绍串口:是一种应用十分广泛的通讯接口,串口成本低,容易使用,通信线路简单,可实现两个设备的互相通信。单片机的串口可以使单片机与单片机,单片机与电脑,单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。使用起来比较简单:
单体架构、集群、分布式、微服务的区别!
码熔burning
微服务 架构 分布式 微服务
目录一、单体架构二、集群♀️♂️三、分布式架构四、微服务架构️五、总结我的其他文章也讲解的比较有趣,如果喜欢博主的讲解方式,可以多多支持一下,感谢!✨更多请看个人主页:码熔burning其他优质专栏:【✨设计模式】【SpringBoot】【多线程】【Redis】…等一、单体架构是什么:想象一下,你开了一家小餐馆,所有的功能都在一个地方完成:点餐、做饭、收银、打扫卫生,所有员工都在一个屋檐下工作
tomcat基础与部署发布
暗黑小菠萝
Tomcat java web
从51cto搬家了,以后会更新在这里方便自己查看。
做项目一直用tomcat,都是配置到eclipse中使用,这几天有时间整理一下使用心得,有一些自己配置遇到的细节问题。
Tomcat:一个Servlets和JSP页面的容器,以提供网站服务。
一、Tomcat安装
安装方式:①运行.exe安装包
&n
网站架构发展的过程
ayaoxinchao
数据库 应用服务器 网站架构
1.初始阶段网站架构:应用程序、数据库、文件等资源在同一个服务器上
2.应用服务和数据服务分离:应用服务器、数据库服务器、文件服务器
3.使用缓存改善网站性能:为应用服务器提供本地缓存,但受限于应用服务器的内存容量,可以使用专门的缓存服务器,提供分布式缓存服务器架构
4.使用应用服务器集群改善网站的并发处理能力:使用负载均衡调度服务器,将来自客户端浏览器的访问请求分发到应用服务器集群中的任何
[信息与安全]数据库的备份问题
comsci
数据库
如果你们建设的信息系统是采用中心-分支的模式,那么这里有一个问题
如果你的数据来自中心数据库,那么中心数据库如果出现故障,你的分支机构的数据如何保证安全呢?
是否应该在这种信息系统结构的基础上进行改造,容许分支机构的信息系统也备份一个中心数据库的文件呢?
&n
使用maven tomcat plugin插件debug关联源代码
商人shang
maven debug 查看源码 tomcat-plugin
*首先需要配置好'''maven-tomcat7-plugin''',参见[[Maven开发Web项目]]的'''Tomcat'''部分。
*配置好后,在[[Eclipse]]中打开'''Debug Configurations'''界面,在'''Maven Build'''项下新建当前工程的调试。在'''Main'''选项卡中点击'''Browse Workspace...'''选择需要开发的
大访问量高并发
oloz
大访问量高并发
大访问量高并发的网站主要压力还是在于数据库的操作上,尽量避免频繁的请求数据库。下面简
要列出几点解决方案:
01、优化你的代码和查询语句,合理使用索引
02、使用缓存技术例如memcache、ecache将不经常变化的数据放入缓存之中
03、采用服务器集群、负载均衡分担大访问量高并发压力
04、数据读写分离
05、合理选用框架,合理架构(推荐分布式架构)。
cache 服务器
小猪猪08
cache
Cache 即高速缓存.那么cache是怎么样提高系统性能与运行速度呢?是不是在任何情况下用cache都能提高性能?是不是cache用的越多就越好呢?我在近期开发的项目中有所体会,写下来当作总结也希望能跟大家一起探讨探讨,有错误的地方希望大家批评指正。
1.Cache 是怎么样工作的?
Cache 是分配在服务器上
mysql存储过程
香水浓
mysql
Description:插入大量测试数据
use xmpl;
drop procedure if exists mockup_test_data_sp;
create procedure mockup_test_data_sp(
in number_of_records int
)
begin
declare cnt int;
declare name varch
CSS的class、id、css文件名的常用命名规则
agevs
JavaScript UI 框架 Ajax css
CSS的class、id、css文件名的常用命名规则
(一)常用的CSS命名规则
头:header
内容:content/container
尾:footer
导航:nav
侧栏:sidebar
栏目:column
页面外围控制整体布局宽度:wrapper
左右中:left right
全局数据源
AILIKES
java tomcat mysql jdbc JNDI
实验目的:为了研究两个项目同时访问一个全局数据源的时候是创建了一个数据源对象,还是创建了两个数据源对象。
1:将diuid和mysql驱动包(druid-1.0.2.jar和mysql-connector-java-5.1.15.jar)copy至%TOMCAT_HOME%/lib下;2:配置数据源,将JNDI在%TOMCAT_HOME%/conf/context.xml中配置好,格式如下:&l
MYSQL的随机查询的实现方法
baalwolf
mysql
MYSQL的随机抽取实现方法。举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在ORDER BY从句里面不能使用RAND()函数,因为这样会导致数据列被多次扫描。但是在MYSQL 3.23版本中,
JAVA的getBytes()方法
bijian1013
java eclipse unix OS
在Java中,String的getBytes()方法是得到一个操作系统默认的编码格式的字节数组。这个表示在不同OS下,返回的东西不一样!
String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示,如:
byte[] b_gbk = "
AngularJS中操作Cookies
bijian1013
JavaScript AngularJS Cookies
如果你的应用足够大、足够复杂,那么你很快就会遇到这样一咱种情况:你需要在客户端存储一些状态信息,这些状态信息是跨session(会话)的。你可能还记得利用document.cookie接口直接操作纯文本cookie的痛苦经历。
幸运的是,这种方式已经一去不复返了,在所有现代浏览器中几乎
[Maven学习笔记五]Maven聚合和继承特性
bit1129
maven
Maven聚合
在实际的项目中,一个项目通常会划分为多个模块,为了说明问题,以用户登陆这个小web应用为例。通常一个web应用分为三个模块:
1. 模型和数据持久化层user-core,
2. 业务逻辑层user-service以
3. web展现层user-web,
user-service依赖于user-core
user-web依赖于user-core和use
【JVM七】JVM知识点总结
bit1129
jvm
1. JVM运行模式
1.1 JVM运行时分为-server和-client两种模式,在32位机器上只有client模式的JVM。通常,64位的JVM默认都是使用server模式,因为server模式的JVM虽然启动慢点,但是,在运行过程,JVM会尽可能的进行优化
1.2 JVM分为三种字节码解释执行方式:mixed mode, interpret mode以及compiler
linux下查看nginx、apache、mysql、php的编译参数
ronin47
在linux平台下的应用,最流行的莫过于nginx、apache、mysql、php几个。而这几个常用的应用,在手工编译完以后,在其他一些情况下(如:新增模块),往往想要查看当初都使用了那些参数进行的编译。这时候就可以利用以下方法查看。
1、nginx
[root@361way ~]# /App/nginx/sbin/nginx -V
nginx: nginx version: nginx/
unity中运用Resources.Load的方法?
brotherlamp
unity视频 unity资料 unity自学 unity unity教程
问:unity中运用Resources.Load的方法?
答:Resources.Load是unity本地动态加载资本所用的方法,也即是你想动态加载的时分才用到它,比方枪弹,特效,某些实时替换的图像什么的,主张此文件夹不要放太多东西,在打包的时分,它会独自把里边的一切东西都会集打包到一同,不论里边有没有你用的东西,所以大多数资本应该是自个建文件放置
1、unity实时替换的物体即是依据环境条件
线段树-入门
bylijinnan
java 算法 线段树
/**
* 线段树入门
* 问题:已知线段[2,5] [4,6] [0,7];求点2,4,7分别出现了多少次
* 以下代码建立的线段树用链表来保存,且树的叶子结点类似[i,i]
*
* 参考链接:http://hi.baidu.com/semluhiigubbqvq/item/be736a33a8864789f4e4ad18
* @author lijinna
全选与反选
chicony
全选
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>全选与反选</title>
vim一些简单记录
chenchao051
vim
mac在/usr/share/vim/vimrc linux在/etc/vimrc
1、问:后退键不能删除数据,不能往后退怎么办?
答:在vimrc中加入set backspace=2
2、问:如何控制tab键的缩进?
答:在vimrc中加入set tabstop=4 (任何
Sublime Text 快捷键
daizj
快捷键 sublime
[size=large][/size]Sublime Text快捷键:Ctrl+Shift+P:打开命令面板Ctrl+P:搜索项目中的文件Ctrl+G:跳转到第几行Ctrl+W:关闭当前打开文件Ctrl+Shift+W:关闭所有打开文件Ctrl+Shift+V:粘贴并格式化Ctrl+D:选择单词,重复可增加选择下一个相同的单词Ctrl+L:选择行,重复可依次增加选择下一行Ctrl+Shift+L:
php 引用(&)详解
dcj3sjt126com
PHP
在PHP 中引用的意思是:不同的名字访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的指针里面存储的是变量的内容在内存中存放的地址 变量的引用 PHP 的引用允许你用两个变量来指向同一个内容 复制代码代码如下:
<?
$a="ABC";
$b =&$a;
echo
SVN中trunk,branches,tags用法详解
dcj3sjt126com
SVN
Subversion有一个很标准的目录结构,是这样的。比如项目是proj,svn地址为svn://proj/,那么标准的svn布局是svn://proj/|+-trunk+-branches+-tags这是一个标准的布局,trunk为主开发目录,branches为分支开发目录,tags为tag存档目录(不允许修改)。但是具体这几个目录应该如何使用,svn并没有明确的规范,更多的还是用户自己的习惯。
对软件设计的思考
e200702084
设计模式 数据结构 算法 ssh 活动
软件设计的宏观与微观
软件开发是一种高智商的开发活动。一个优秀的软件设计人员不仅要从宏观上把握软件之间的开发,也要从微观上把握软件之间的开发。宏观上,可以应用面向对象设计,采用流行的SSH架构,采用web层,业务逻辑层,持久层分层架构。采用设计模式提供系统的健壮性和可维护性。微观上,对于一个类,甚至方法的调用,从计算机的角度模拟程序的运行情况。了解内存分配,参数传
同步、异步、阻塞、非阻塞
geeksun
非阻塞
同步、异步、阻塞、非阻塞这几个概念有时有点混淆,在此文试图解释一下。
同步:发出方法调用后,当没有返回结果,当前线程会一直在等待(阻塞)状态。
场景:打电话,营业厅窗口办业务、B/S架构的http请求-响应模式。
异步:方法调用后不立即返回结果,调用结果通过状态、通知或回调通知方法调用者或接收者。异步方法调用后,当前线程不会阻塞,会继续执行其他任务。
实现:
Reverse SSH Tunnel 反向打洞實錄
hongtoushizi
ssh
實際的操作步驟:
# 首先,在客戶那理的機器下指令連回我們自己的 Server,並設定自己 Server 上的 12345 port 會對應到幾器上的 SSH port
ssh -NfR 12345:localhost:22 fred@myhost.com
# 然後在 myhost 的機器上連自己的 12345 port,就可以連回在客戶那的機器
ssh localhost -p 1
Hibernate中的缓存
Josh_Persistence
一级缓存 Hiberante缓存 查询缓存 二级缓存
Hibernate中的缓存
一、Hiberante中常见的三大缓存:一级缓存,二级缓存和查询缓存。
Hibernate中提供了两级Cache,第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存。这一级别的缓存是由hibernate管理的,一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或群集范围的缓存。这一级别的缓存
对象关系行为模式之延迟加载
home198979
PHP 架构 延迟加载
形象化设计模式实战 HELLO!架构
一、概念
Lazy Load:一个对象,它虽然不包含所需要的所有数据,但是知道怎么获取这些数据。
延迟加载貌似很简单,就是在数据需要时再从数据库获取,减少数据库的消耗。但这其中还是有不少技巧的。
二、实现延迟加载
实现Lazy Load主要有四种方法:延迟初始化、虚
xml 验证
pengfeicao521
xml xml解析
有些字符,xml不能识别,用jdom或者dom4j解析的时候就报错
public static void testPattern() {
// 含有非法字符的串
String str = "Jamey친ÑԂ
div设置半透明效果
spjich
css 半透明
为div设置如下样式:
div{filter:alpha(Opacity=80);-moz-opacity:0.5;opacity: 0.5;}
说明:
1、filter:对win IE设置半透明滤镜效果,filter:alpha(Opacity=80)代表该对象80%半透明,火狐浏览器不认2、-moz-opaci
你真的了解单例模式么?
w574240966
java 单例 设计模式 jvm
单例模式,很多初学者认为单例模式很简单,并且认为自己已经掌握了这种设计模式。但事实上,你真的了解单例模式了么。
一,单例模式的5中写法。(回字的四种写法,哈哈。)
1,懒汉式
(1)线程不安全的懒汉式
public cla