前言
现在正在出一个查漏补缺专题
系列教程, 篇幅会较多, 喜爱的话,给个关注❤️ ~
本专题主要以Java
语言为主, 好了, 废话不多说直接开整吧~
Spring中bean的生命周期
在Spring
框架中,Bean
的生命周期能够被分为多个阶段,包含实例化、特点赋值、初始化、毁掉等。下面是Spring
中Bean
的生命周期的详细进程:
-
实例化:当
Spring
容器发动时,会依据装备文件或注解等办法来创立Bean
的实例。这个阶段是经过调用Bean
的结构函数来完成的。 -
特点赋值:在实例化完成后,
Spring
容器会依据装备文件或注解等办法来设置Bean
的特点。这能够经过setter
办法进行特点注入,或许运用字段注入。 -
初始化前回调办法:在特点赋值完成后,
Spring
容器会调用Bean的初始化前回调办法(假如有的话)。这些办法能够完成InitializingBean
接口的afterPropertiesSet
()办法,或许运用@PostConstruct
注解进行符号。 -
自界说初始化办法:在初始化前回调办法履行完毕后,
Spring
容器会调用Bean
的自界说初始化办法(假如有的话)。这些办法是由开发人员自己界说的,并在装备文件或注解中进行指定。 -
初始化后回调办法:在自界说初始化办法履行完毕后,
Spring
容器会调用Bean
的初始化后回调办法(假如有的话)。这些办法能够完成InitializingBean
接口的afterPropertiesSet()
办法,或许运用@PostConstruct
注解进行符号。 -
运用
Bean
:在初始化完成后,Bean
能够被运用程序运用。它们能够被注入到其他Bean
中,或许经过Spring
容器获取并运用。 -
毁掉前回调办法:当
Spring
容器封闭时,或许从容器中移除Bean
时,会调用Bean
的毁掉前回调办法(假如有的话)。这些办法能够完成DisposableBean
接口的destroy()
办法,或许运用@PreDestroy
注解进行符号。 -
自界说毁掉办法:在毁掉前回调办法履行完毕后,
Spring
容器会调用Bean
的自界说毁掉办法(假如有的话)。这些办法是由开发人员自己界说的,并在装备文件或注解中进行指定。
需求注意的是,不是所有的Bean
都需求界说初始化和毁掉办法,这是可选的。假如Bean
没有界说这些办法,它们的生命周期将仅限于实例化、特点赋值和运用阶段。
经过了解Spring
中Bean
的生命周期,能够在需求时履行一些特定的操作,例如在初始化时履行一些初始化逻辑或资源的分配,并在毁掉时开释这些资源。这为开发人员供给了更大的灵活性和控制权。
Mysql binlog日志监听详细怎样完成
运用mysql-binlog-connector-java
能够完成对MySQL Binlog
日志的监听。这是一个开源的Java
库,它供给了与MySQL
的Binlog
日志进行交互的功用。
下面是运用mysql-binlog-connector-java
库进行MySQL Binlog日志监听的一般进程:
- 引进依靠:在你的Java项目中,需求添加
mysql-binlog-connector-java
的依靠。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
- 创立衔接:运用
mysql-connector-java
库创立与MySQL数据库的衔接。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");
- 装备Binlog监听器:创立一个
BinaryLogClient
目标并装备相应的监听器。
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.EventData;
import com.github.shyiko.mysql.binlog.event.EventType;
import com.github.shyiko.mysql.binlog.event.deserialization.EventDeserializer;
BinaryLogClient client = new BinaryLogClient("localhost", 3306, "username", "password");
EventDeserializer eventDeserializer = new EventDeserializer();
// 设置事情反序列化器的一些选项(可选)
eventDeserializer.setCompatibilityMode(EventDeserializer.CompatibilityMode.DATE_AND_TIME_AS_LONG);
client.setEventDeserializer(eventDeserializer);
client.registerEventListener(event -> {
EventData eventData = event.getData();
EventType eventType = event.getHeader().getEventType();
// 处理不同的事情类型
if (eventType == EventType.WRITE_ROWS) {
// 处理刺进数据事情
// eventData供给了事情相关的数据,能够解析出详细的操作内容
} else if (eventType == EventType.UPDATE_ROWS) {
// 处理更新数据事情
} else if (eventType == EventType.DELETE_ROWS) {
// 处理删去数据事情
}
// ...
});
- 发动监听:经过调用
connect()
办法发动Binlog监听。
client.connect();
监听器现在会接收到MySQL Binlog日志中发生的事情,并依据事情类型履行相应的操作。
- 封闭衔接:在不需求监听时,能够经过调用
disconnect()
办法封闭与MySQL数据库的衔接。
client.disconnect();
请注意,上述代码示例仅供给了根本的监听和处理Binlog
事情的框架,你可能需求依据实践需求进行更详细的处理和业务逻辑。此外,你还需求保证MySQL
服务器启用了二进制日志(Binary Log
)功用,以便进行Binlog
日志的监听。
怎么保证redis和mysql数据共同性,有哪些办法?
要保证Redis
和MySQL
之间的数据共同性,需求考虑数据的读取、更新和同步的进程。
- 数据写入:
- 当有数据要写入MySQL时,首要将数据写入MySQL数据库。
- 接着,经过数据库的触发器或其他办法,将写入操作异步地发送到Redis,更新对应的缓存数据。
// 示例代码(Java + MySQL)
// 将数据写入MySQL数据库
public void writeToMySQL(Data data) {
// 履行刺进或更新操作
String sql = "INSERT INTO my_table (id, name, value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE name = VALUES(name), value = VALUES(value)";
try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");
PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setInt(1, data.getId());
statement.setString(2, data.getName());
statement.setString(3, data.getValue());
statement.executeUpdate();
} catch (SQLException e) {
// 处理反常
}
// 异步将写入操作发送到Redis
asyncUpdateRedisCache(data);
}
- 数据读取:
- 当需求读取数据时,首要从Redis缓存中查询数据。
- 假如缓存中存在数据,则直接回来。
- 假如缓存中不存在数据,则从MySQL数据库读取数据,并将数据存入Redis缓存中。
// 示例代码(Java + Redis)
// 从Redis缓存中读取数据
public Data readFromRedis(int id) {
try (Jedis jedis = jedisPool.getResource()) {
String cacheKey = "data:" + id;
String cachedData = jedis.get(cacheKey);
if (cachedData != null) {
// 缓存射中,直接回来数据
return parseDataFromJson(cachedData);
} else {
// 缓存未射中,从MySQL数据库读取数据
Data data = readFromMySQL(id);
if (data != null) {
// 将数据存入Redis缓存
jedis.set(cacheKey, toJson(data));
}
return data;
}
}
}
// 从MySQL数据库读取数据
private Data readFromMySQL(int id) {
// 履行查询操作,获取数据
String sql = "SELECT id, name, value FROM my_table WHERE id = ?";
try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");
PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setInt(1, id);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
// 解析并回来数据
Data data = new Data();
data.setId(resultSet.getInt("id"));
data.setName(resultSet.getString("name"));
data.setValue(resultSet.getString("value"));
return data;
}
}
} catch (SQLException e) {
// 处理反常
}
return null;
}
- 数据更新同步:
- 在MySQL中进行数据更新时,保证同步更新Redis缓存。
能够经过数据库的触发器或其他办法,在数据更新之后,异步地发送更新操作到Redis,使Redis中的缓存数据坚持与MySQL共同。
// 示例代码(MySQL触发器)
CREATE TRIGGER my_table_after_update
AFTER UPDATE ON my_table
FOR EACH ROW
BEGIN
DECLARE jsonString VARCHAR(255);
SET jsonString = CONCAT('{"id":', NEW.id, ',"name":"', NEW.name, '","value":"', NEW.value, '"}');
CALL sys_exec('redis-cli SET data:' + CAST(NEW.id AS CHAR) + ' ' + jsonString);
END;
这只是一种常见的完成方案,详细的完成办法能够依据实践需求进行调整。需求注意的是,异步更新Redis缓存的操作需求额定的机制,例如运用音讯行列或异步任务来处理。
MD5加密的算法是怎样完成的,能讲讲原理吗
MD5(Message Digest Algorithm 5)
是一种常用的音讯摘要算法,用于将任意长度的数据生成固定长度(128位)的哈希值。
MD5
算法的根本原理:
- 数据填充:对待加密数据进行填充,使其长度满意必定要求,一般是64位的倍数。
- 初始化:将一些预界说的常量赋值给四个32位寄存器(A、B、C、D)。
- 处理数据:将填充后的数据划分为若干个512位的数据块,并对每个数据块进行处理。
- 对每个数据块进行四轮循环处理,每轮循环都有16个进程。
- 每轮循环中,依据当时数据块中的数据和上一轮循环中的寄存器值进行一系列的位运算和逻辑运算。
- 每轮循环的成果都会更新寄存器的值。
- 成果输出:将最终一轮循环处理的寄存器值按次序衔接起来,得到128位的哈希值。
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Example {
public static void main(String[] args) {
String input = "Hello, World!";
String md5Hash = getMD5Hash(input);
System.out.println("MD5 Hash: " + md5Hash);
}
public static String getMD5Hash(String input) {
try {
// 创立MD5摘要算法实例
MessageDigest md = MessageDigest.getInstance("MD5");
// 核算哈希值
byte[] hashBytes = md.digest(input.getBytes());
// 转换为十六进制表示
BigInteger hashNumber = new BigInteger(1, hashBytes);
String hashString = hashNumber.toString(16);
// 假如哈希值的长度不足32位,前面补0
while (hashString.length() < 32) {
hashString = "0" + hashString;
}
return hashString;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}
在示例代码中,咱们运用java.security.MessageDigest
类供给的API来核算MD5哈希值。首要创立了一个MessageDigest
实例,并指定算法为”MD5″。然后将待加密的数据转换为字节数组,并经过digest()
办法核算哈希值。最终,将哈希值转换为十六进制字符串表示,并补足长度为32位。
需求注意的是,MD5算法是一种单向散列函数,它不可逆。因而,经过MD5哈希值无法复原原始数据。此外,MD5算法现在现已被认为不是足够安全,因为它存在碰撞(不同数据生成相同哈希值)的危险。在实践运用中,更引荐运用更安全的哈希算法,如SHA-256
等。
找出字符串中第一个匹配项的下标(力扣28题)
给你两个字符串 haystack
和needle
,请你在 haystack
字符串中找出needle
字符串的第一个匹配项的下标(下标从 0 开始)。假如needle
不是 haystack
的一部分,则回来 -1 。
KMP (Knuth-Morris-Pratt)
算法完成:
public class KMPSearch {
public static void main(String[] args) {
String text = "Hello, World!";
String pattern = "Hells";
int index = kmpSearch(text, pattern);
System.out.println("First match index: " + index);
// -1
}
public static int kmpSearch(String text, String pattern) {
if (text == null || pattern == null || text.isEmpty() || pattern.isEmpty()) {
return -1;
}
int[] lps = computeLPSArray(pattern);
int i = 0; // text中的索引
int j = 0; // pattern中的索引
while (i < text.length()) {
if (text.charAt(i) == pattern.charAt(j)) {
i++;
j++;
if (j == pattern.length()) {
return i - j; // 匹配成功,回来第一个匹配项的下标
}
} else {
if (j != 0) {
j = lps[j - 1]; // 回溯到最长公共前后缀的下一个方位
} else {
i++; // 没有找到匹配项,持续在text中前进
}
}
}
return -1; // 没有找到匹配项
}
private static int[] computeLPSArray(String pattern) {
int[] lps = new int[pattern.length()];
int len = 0; // 最长公共前后缀的长度
int i = 1;
while (i < pattern.length()) {
if (pattern.charAt(i) == pattern.charAt(len)) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1]; // 回溯到前一个方位持续匹配
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
}
KMP
算法的时刻复杂度为O(n + m)
,其中n是文本字符串的长度,m是形式字符串的长度。
在KMP算法中,首要需求核算形式字符串的最长公共前后缀(Longest Proper Prefix which is also Suffix
,简称LPS
)数组,该进程的时刻复杂度为O(m)
。
接下来,在搜索进程中,咱们运用两个指针i和j别离指向文本字符串和形式字符串的当时方位。在每一次比较进程中,i和j要么都向前移动一步,要么只有j回溯到LPS数组的值。因为每个方位的字符最多被比较一次,因而总共进行n次比较。
因而,总的时刻复杂度为O(n + m)
。
KMP
算法经过运用形式字符串的信息,避免了不必要的回溯,提高了字符串匹配的效率。比较于朴素的字符串匹配算法,其时刻复杂度大大减少。
结束语
我们能够针对自己薄弱的地方进行复习, 然后多总结,形成自己的了解,不要去背~
本着把自己知道的都告知我们,假如本文对您有所帮助,点赞+关注
鼓舞一下呗~
相关文章
- 查漏补缺第一期(Redis相关)
- 查漏补缺第二期(synchronized & 锁升级)
- 查漏补缺第三期(分布式事务相关)
- 查漏补缺第四期(Mysql相关)
- 查漏补缺第五期(HashMap & ConcurrentHashMap)
- 查漏补缺第六期(京东一面)
- 查漏补缺第七期(美团到店一面)
- 查漏补缺第八期(阿里一面)
- 查漏补缺第九期(阿里二面)
- 查漏补缺第十期(网易实习一面)
- 查漏补缺第十一期(网易实习二面)
项目源码(源码已更新 欢迎star⭐️)
- java-interview-all: https://github.com/qiuChengleiy/java-interview-all
往期规划形式相关文章
- 一起来学规划形式之知道规划形式
- 一起来学规划形式之单例形式
- 一起来学规划形式之工厂形式
- 一起来学规划形式之建造者形式
- 一起来学规划形式之原型形式
- 一起来学规划形式之适配器形式
- 一起来学规划形式之桥接形式
- 一起来学规划形式之组合形式
- 一起来学规划形式之装修器形式
- 一起来学规划形式之外观形式
- 一起来学规划形式之享元形式
- 一起来学规划形式之署理形式
- 一起来学规划形式之职责链形式
- 一起来学规划形式之指令形式
- 一起来学规划形式之解释器形式
- 一起来学规划形式之迭代器形式
- 一起来学规划形式之中介者形式
- 一起来学规划形式之备忘录形式
- 一起来学规划形式之观察者形式
- 一起来学规划形式之状态形式
- 一起来学规划形式之策略形式
- 一起来学规划形式之模板办法形式
- 一起来学规划形式之访问者形式
- 一起来学规划形式之依靠注入形式
规划形式项目源码(源码已更新 欢迎star⭐️)
- java-design-mode-all: https://github.com/qiuChengleiy/java-design-mode-all
Kafka 专题学习
- 一起来学kafka之Kafka集群搭建
- 一起来学kafka之整合SpringBoot根本运用
- 一起来学kafka之整合SpringBoot深化运用(一)
- 一起来学kafka之整合SpringBoot深化运用(二)
- 一起来学kafka之整合SpringBoot深化运用(三)
项目源码(源码已更新 欢迎star⭐️)
- springboot-kafka-all: https://github.com/qiuChengleiy/springboot-kafka-all
ElasticSearch 专题学习
-
运用docker搭建es集群
-
一起来学ElasticSearch(一)
-
一起来学ElasticSearch(二)
-
一起来学ElasticSearch(三)
-
一起来学ElasticSearch(四)
-
一起来学ElasticSearch(五)
-
一起来学ElasticSearch(六)
-
一起来学ElasticSearch(七)
-
一起来学ElasticSearch(八)
-
一起来学ElasticSearch(九)
-
一起来学ElasticSearch(十)
-
一起来学ElasticSearch之整合SpringBoot(一)
-
一起来学ElasticSearch之整合SpringBoot(二)
-
一起来学ElasticSearch之整合SpringBoot(三)
项目源码(源码已更新 欢迎star⭐️)
- springboot-es-all: https://github.com/qiuChengleiy/springboot-es-all
往期并发编程内容引荐
- Java多线程专题之线程与进程概述
- Java多线程专题之线程类和接口入门
- Java多线程专题之进阶学习Thread(含源码剖析)
- Java多线程专题之Callable、Future与FutureTask(含源码剖析)
- 面试官: 有了解过线程组和线程优先级吗
- 面试官: 说一下线程的生命周期进程
- 面试官: 说一下线程间的通信
- 面试官: 说一下Java的共享内存模型
- 面试官: 有了解过指令重排吗,什么是happens-before
- 面试官: 有了解过volatile关键字吗 说说看
- 面试官: 有了解过Synchronized吗 说说看
- Java多线程专题之Lock锁的运用
- 面试官: 有了解过ReentrantLock的底层完成吗?说说看
- 面试官: 有了解过CAS和原子操作吗?说说看
- Java多线程专题之线程池的根本运用
- 面试官: 有了解过线程池的工作原理吗?说说看
- 面试官: 线程池是怎么做到线程复用的?有了解过吗,说说看
- 面试官: 堵塞行列有了解过吗?说说看
- 面试官: 堵塞行列的底层完成有了解过吗? 说说看
- 面试官: 同步容器和并发容器有用过吗? 说说看
- 面试官: CopyOnWrite容器有了解过吗? 说说看
- 面试官: Semaphore在项目中有运用过吗?说说看(源码剖析)
- 面试官: Exchanger在项目中有运用过吗?说说看(源码剖析)
- 面试官: CountDownLatch有了解过吗?说说看(源码剖析)
- 面试官: CyclicBarrier有了解过吗?说说看(源码剖析)
- 面试官: Phaser有了解过吗?说说看
- 面试官: Fork/Join 有了解过吗?说说看(含源码剖析)
- 面试官: Stream并行流有了解过吗?说说看
引荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)
-
springboot-all https://github.com/qiuChengleiy/springboot-all.git
-
SpringBoot系列教程合集
-
一起来学SpringCloud合集
-
SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 完成授权码形式的服务认证(一)
-
SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 完成授权码形式的服务认证(二)
博客(阅读体会较佳)
- 我的博客(阅读体会较佳)