Spring Boot 依赖注入与Bean管理:JavaConfig如何取代XML?

大家好呀!今天我们来聊一个超级实用的技术话题 —— Spring Boot 中的依赖注入和Bean管理,特别是JavaConfig是如何一步步取代XML配置的。我知道很多小伙伴一听到"依赖注入"、"Bean管理"这些词就头大,别担心!我会用最简单的方式,就像教小朋友一样,带你彻底搞懂这些概念!😊

📚 第一章:什么是依赖注入?先来个生活小例子!

想象一下,你是一个小厨师👨🍳,要做一道美味的番茄炒蛋🍳。你需要什么呢?需要番茄、鸡蛋、油、盐对吧?这些"材料"就是你的"依赖"!

传统方式:你自己去菜市场买番茄、去养鸡场找鸡蛋、去超市买油和盐…累不累?😫

依赖注入方式:有个神奇的冰箱(Spring容器),里面已经准备好了所有材料,你只需要说"我要做番茄炒蛋",冰箱就自动把材料给你准备好!太方便了吧!😍

// 传统方式:自己创建所有依赖
Tomato tomato = new Tomato();
Egg egg = new Egg();
Oil oil = new Oil();
Salt salt = new Salt();
ScrambledEggWithTomato dish = new ScrambledEggWithTomato(tomato, egg, oil, salt);// 依赖注入方式:告诉Spring你需要什么,它自动给你
@Autowired
ScrambledEggWithTomato dish;  // Spring会自动把材料准备好并组装好这道菜!

看到区别了吗?依赖注入(Dependency Injection, DI)就是把对象所需要的其他对象(依赖)自动"注入"给它,而不是让它自己创建。这样代码更干净、更灵活!👍

🧩 第二章:什么是Bean?为什么需要管理它们?

在Spring的世界里,Bean就是由Spring容器管理的对象。就像冰箱里的食材一样,都是被冰箱(Spring容器)管理着的。

为什么需要管理Bean呢? 🤔

  1. 控制反转(IoC):对象的创建和管理权从程序员手里转交给了Spring容器
  2. 单例管理:确保某些重要的对象只有一个实例(比如数据库连接)
  3. 依赖解析:自动处理对象之间的复杂依赖关系
  4. 生命周期管理:控制对象的创建、初始化、销毁等过程

以前,我们用XML文件来配置这些Bean,就像写购物清单一样:

这种方式虽然能工作,但有好多问题:

  • XML文件会变得超级大,难以维护 📜
  • 没有类型安全检查,容易写错 ❌
  • 配置和代码分离,跳来跳去看很麻烦 🔍
  • 重构困难,改个类名要到处改XML 😫

💎 第三章:JavaConfig闪亮登场!✨

于是,Spring 3.0引入了JavaConfig,就是用Java类来代替XML配置!这就像是用智能手机📱取代老式按键手机一样,是巨大的进步!

JavaConfig的核心是@Configuration注解。看看同样的配置用Java怎么写:

@Configuration
public class KitchenConfig {@Beanpublic Tomato tomato() {return new Tomato();}@Beanpublic Egg egg() {return new Egg();}@Beanpublic Oil oil() {return new Oil();}@Beanpublic Salt salt() {return new Salt();}@Beanpublic ScrambledEggWithTomato dish(Tomato tomato, Egg egg, Oil oil, Salt salt) {return new ScrambledEggWithTomato(tomato, egg, oil, salt);}
}

哇!是不是清晰多了?👏 JavaConfig的好处太多了:

类型安全:编译器会检查类型对不对
易于重构:IDE可以自动重命名
更强大:可以写逻辑、调用方法等
更简洁:很多配置可以用注解简化
与代码在一起:不用在XML和Java间跳来跳去

🏗️ 第四章:Spring Boot如何更进一步简化配置?

Spring Boot在JavaConfig基础上又做了超级多的自动化!它就像个智能助手🤖,能根据你的依赖自动配置很多东西。

Spring Boot的核心魔法:

  1. 自动配置(Auto-configuration):根据classpath中的jar包自动配置Bean
  2. 起步依赖(Starter Dependencies):把常用依赖打包成"套餐"
  3. 条件化Bean(@Conditional):满足条件才创建Bean
  4. 属性配置(application.properties):外部化配置

举个例子,要配置一个数据库连接,以前要写一大堆:

@Configuration
public class DataSourceConfig {@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");dataSource.setUsername("root");dataSource.setPassword("password");return dataSource;}
}

而在Spring Boot中,只需要在application.properties中写:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

Spring Boot会自动帮你创建DataSource的Bean!如果连这些都不想写,用H2内存数据库的话,甚至什么都不用配置!😲

🎯 第五章:依赖注入的三种主要方式

Spring提供了三种主要的依赖注入方式,就像给冰箱里的食材三种不同的包装方式:

1. 构造器注入 (最推荐!👍)

public class ScrambledEggWithTomato {private final Tomato tomato;private final Egg egg;private final Oil oil;private final Salt salt;// 通过构造方法注入public ScrambledEggWithTomato(Tomato tomato, Egg egg, Oil oil, Salt salt) {this.tomato = tomato;this.egg = egg;this.oil = oil;this.salt = salt;}
}

优点

  • 不可变(final字段)
  • 完全初始化的对象
  • 易于测试
  • Spring官方推荐

2. Setter方法注入

public class ScrambledEggWithTomato {private Tomato tomato;private Egg egg;private Oil oil;private Salt salt;// 通过setter方法注入public void setTomato(Tomato tomato) {this.tomato = tomato;}public void setEgg(Egg egg) {this.egg = egg;}// 其他setter...
}

适用场景

  • 可选依赖
  • 需要重新配置的依赖

3. 字段注入 (不推荐❌)

public class ScrambledEggWithTomato {@Autowiredprivate Tomato tomato;@Autowiredprivate Egg egg;@Autowiredprivate Oil oil;@Autowiredprivate Salt salt;
}

为什么不推荐

  • 难以测试(必须用Spring容器)
  • 隐藏了依赖关系
  • 不能声明为final

🌈 第六章:Bean的作用域 - 控制Bean的生命周期

Spring中的Bean有不同的作用域,就像食材有不同的保质期一样:

  1. Singleton(单例):默认作用域,整个应用只有一个实例 🌟

    @Bean
    @Scope("singleton")  // 可以省略,默认就是
    public Tomato tomato() {return new Tomato();
    }
    
  2. Prototype(原型):每次请求都创建一个新实例 🔄

    @Bean
    @Scope("prototype")
    public Egg egg() {return new Egg();  // 每次获取都会new一个新的
    }
    
  3. Request:每个HTTP请求一个实例 (Web) 🌐

  4. Session:每个HTTP会话一个实例 (Web) 💻

  5. Application:每个ServletContext一个实例 (Web) 🖥️

  6. WebSocket:每个WebSocket会话一个实例 (Web) 🕸️

如何选择?

  • 无状态的服务类通常用singleton
  • 有状态的类考虑用prototype
  • Web相关的作用域用于Web环境

🛠️ 第七章:高级话题 - 条件化Bean与Profile

有时候我们想根据不同的环境创建不同的Bean,比如开发环境和生产环境用不同的数据源。Spring提供了两种主要方式:

1. @Profile - 根据环境激活Bean

@Configuration
public class DataSourceConfig {@Bean@Profile("dev")  // 开发环境用H2内存数据库public DataSource devDataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:schema.sql").build();}@Bean@Profile("prod")  // 生产环境用MySQLpublic DataSource prodDataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://prod-server:3306/mydb");dataSource.setUsername("prod-user");dataSource.setPassword("prod-password");return dataSource;}
}

激活profile的方式:

  • 命令行:--spring.profiles.active=dev
  • 配置文件:spring.profiles.active=dev
  • 环境变量:SPRING_PROFILES_ACTIVE=dev

2. @Conditional - 更灵活的条件判断

@Bean
@Conditional(MyCustomCondition.class)  // 自定义条件
public DataSource dataSource() {// ...
}public class MyCustomCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 这里写判断逻辑,返回true才创建Beanreturn context.getEnvironment().containsProperty("custom.property");}
}

Spring Boot提供了很多现成的条件注解:

  • @ConditionalOnClass:类路径有指定类时生效
  • @ConditionalOnMissingBean:没有指定Bean时生效
  • @ConditionalOnProperty:有指定配置属性时生效
  • @ConditionalOnWebApplication:是Web应用时生效

🔄 第八章:Bean的生命周期回调

有时候我们需要在Bean创建或销毁时做一些事情,Spring提供了几种方式:

  1. 实现接口

    public class MyBean implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {// 初始化逻辑}@Overridepublic void destroy() throws Exception {// 销毁逻辑}
    }
    
  2. 使用注解 (更推荐!):

    public class MyBean {@PostConstructpublic void init() {// 初始化逻辑}@PreDestroypublic void cleanup() {// 销毁逻辑}
    }
    
  3. 在@Bean注解中指定

    @Bean(initMethod = "init", destroyMethod = "cleanup")
    public MyBean myBean() {return new MyBean();
    }
    

执行顺序

  1. 构造函数
  2. @Autowired注入依赖
  3. @PostConstruct方法
  4. …使用Bean…
  5. @PreDestroy方法

🧠 第九章:常见问题与最佳实践

❓ 问题1:什么时候用@Component,什么时候用@Bean?

  • @Component:用在类上,让Spring自动扫描并创建Bean

    @Component
    public class MyService {// ...
    }
    
  • @Bean:用在@Configuration类的方法上,手动定义Bean创建逻辑

    @Configuration
    public class MyConfig {@Beanpublic MyService myService() {return new MyService();}
    }
    

经验法则

  • 自己写的类用@Component
  • 第三方库的类或需要复杂初始化的类用@Bean

❓ 问题2:循环依赖怎么办?

A依赖B,B又依赖A,这就形成了循环依赖。Spring能解决部分循环依赖,但最好避免!

解决方案

  1. 重新设计,打破循环
  2. 使用setter注入代替构造器注入
  3. 使用@Lazy延迟初始化
    @Component
    public class A {private final B b;public A(@Lazy B b) {  // 延迟初始化this.b = b;}
    }
    

❓ 问题3:如何选择XML和JavaConfig?

虽然JavaConfig是主流,但XML在以下情况仍有价值:

  • 遗留系统迁移
  • 需要在不修改代码的情况下更改配置
  • 某些复杂的Spring集成场景

但在新项目中,强烈建议使用JavaConfig!🎯

🚀 第十章:Spring Boot自动配置的魔法揭秘

Spring Boot的自动配置看起来像魔法,但其实原理很简单:

  1. @SpringBootApplication 是一个组合注解,包含:

    • @SpringBootConfiguration:标识这是配置类
    • @EnableAutoConfiguration:启用自动配置
    • @ComponentScan:自动扫描组件
  2. 自动配置原理

    • Spring Boot在spring-boot-autoconfigure.jar的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中定义了很多自动配置类
    • 这些类用@Conditional决定是否生效
    • 根据classpath中的类决定激活哪些配置
  3. 查看自动配置

    • 启动时添加--debug参数可以看到哪些自动配置生效了
    • 或者使用spring.autoconfigure.exclude排除某些自动配置
// 例如DataSourceAutoConfiguration的简化版
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic DataSource dataSource(DataSourceProperties properties) {// 根据配置创建DataSource}
}

🎁 第十一章:自定义Starter - 把你的配置分享给他人

如果你想把自己的配置打包成一个Starter给别人用,非常简单:

  1. 创建一个普通的Spring Boot项目

  2. 添加你的@Configuration类

  3. 在src/main/resources/META-INF下创建:

    • spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,写入你的配置类全名
    • additional-spring-configuration-metadata.json文件(可选,提供配置元数据)
  4. 打包发布,别人就可以通过引入你的starter来获得自动配置了!

📝 第十二章:总结 - JavaConfig vs XML 终极对决

特性JavaConfigXML配置
类型安全✅ 编译器检查❌ 运行时才发现错误
重构友好✅ IDE支持❌ 需要手动改
表达能力✅ 完整Java语法❌ 有限XML语法
灵活性✅ 可以写逻辑❌ 静态配置
可读性✅ 结构清晰❌ 嵌套复杂
配置集中度✅ 与代码一起❌ 分散在XML文件
学习曲线低(纯Java)中(特殊语法)
社区趋势主流逐渐淘汰

最终结论:在新项目中毫不犹豫选择JavaConfig!XML只应在维护旧系统时使用。🎉

🌟 第十三章:实战小练习

为了巩固知识,来做几个小练习吧!

练习1:创建一个配置类,定义以下Bean

  • 一个单例的UserService
  • 一个原型的Task
  • 一个依赖UserServiceProjectService

练习2:创建一个条件化Bean

  • 当系统属性"cache.enabled"=true时才创建CacheManager Bean

练习3:模拟一个Starter

  • 创建一个自动配置类,当classpath中有com.example.MyLib时自动配置MyLibAutoConfiguration

(答案可以在Spring官方文档或我的GitHub上找到哦~)

💖 最后的话

哇!不知不觉我们已经写了这么多内容!从最基础的依赖注入概念,到JavaConfig如何取代XML,再到Spring Boot的自动配置魔法,最后到创建自己的Starter。希望你现在对Spring的依赖注入和Bean管理有了清晰的认识!😊

记住,依赖注入的核心思想是"不要自己找依赖,让框架给你",而JavaConfig就是用Java代码清晰表达这种关系的最佳方式

如果你有任何问题,欢迎在评论区留言!我会尽力解答。也欢迎关注我的账号,我会持续分享更多Spring Boot和Java开发的干货内容!🚀

Happy Coding! 💻✨

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/77410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全志H5,NanopiKP1lus移植QT5.12记录

移植步骤 机器环境下载QT5.12.0源码安装交叉编译器修改qmake.conf文件配置编译选项qt5的configure选项说明基本配置选项编译器和链接器选项功能模块配置第三方库集成注意事项 配置过程报错解决配置完成编译过程报错解决编译完成将arm-qt文件夹传送到开发板配置板子环境变量运行…

STM32单片机C语言

1、stdint.h简介 stdint.h 是从 C99 中引进的一个标准 C 库的文件 路径:D:\MDK5.34\ARM\ARMCC\include 大家都统一使用一样的标准,这样方便移植 配置MDK支持C99 位操作 如何给寄存器某个值赋值 举个例子:uint32_t temp 0; 宏定义 带参…

【专题刷题】双指针(四):最接近的三数之和,接雨水

📝前言说明: 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分每题主要记录:(1)本人解法 本人屎山代码;(2)优质解法 优质代码;&#xff…

chili3d调试笔记3 加入c++ 大模型对话方法 cmakelists精读

加入 #include <emscripten/bind.h> #include <emscripten/val.h> #include <nlohmann/json.hpp> 怎么加包 函数直接用emscripten::function&#xff0c;如&#xff1a; emscripten::function("send_to_llm", &send_to_llm); set (CMAKE_C…

[Redis]1-高效的数据结构P2-Set

按照惯例&#xff0c;先丢一个官网文档链接。 上篇我们已经了解了高效的数据结构P1-String与Hash。 这篇&#xff0c;我们继续来了解Redis的 Set 与 Sorted set。 目录 有序集合 Sorted set底层实现 集合 Set总结资料引用 有序集合 Sorted set Redis 有序集合是一组唯一的字符…

Python + Playwright:使用正则表达式增强自动化测试

Python + Playwright:使用正则表达式增强自动化测试 前言一、 为什么选择正则表达式?二、 Playwright 中集成正则表达式:途径与方法三、 实战应用:正则表达式解决典型测试难题场景 1:定位 ID 或 Class 包含动态部分的元素场景 2:验证包含可变数字或文本的提示信息场景 3:…

VASP 6.4.1 Ubuntu系统编译安装手册

VASP 6.4.1 Ubuntu系统编译安装手册 &#xff08;基于Ubuntu 22.04 LTS&#xff0c;适用x86_64架构&#xff09; 文章目录 VASP 6.4.1 Ubuntu系统编译安装手册第一章 系统环境深度配置1.1 硬件兼容性验证1.2 操作系统环境准备1.3 数学库深度优化配置 第二章 编译环境深度调优2…

uniapp h5接入地图选点组件

uniapp h5接入地图选点组件 1、申请腾讯地图key2、代码接入2.1入口页面 &#xff08;pages/map/map&#xff09;templatescript 2.2选点页面&#xff08;pages/map/mapselect/mapselect&#xff09;templatescript 该内容只针对uniapp 打包h5接入地图选点组件做详细说明&#x…

java输出、输入语句

先创建一个用于测试的java 编写程序 #java.util使java标准库的一个包&#xff0c;这里拉取Scanner类 import java.util.Scanner;public class VariableTest {public static void main(String[] args) {#创建一个 Scanner 对象Scanner scanner new Scanner(System.in);System.…

AI Agents系列之构建多智能体系统

&#x1f9e0; 向所有学习者致敬&#xff01; “学习不是装满一桶水&#xff0c;而是点燃一把火。” —— 叶芝 我的博客主页&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 欢迎点击加入AI人工智能社区&#xff01; &#x1f680; 让我们一起努力&#xff0c;共创…

04.Spring 框架注解体系详解

Spring 框架注解体系详解 本文详细介绍 Spring、Spring Boot 及 Spring Cloud 中常用注解的用途、生命周期及使用方式&#xff0c;帮助开发者更深入理解 Spring 注解驱动编程模式。 参考来源&#xff1a;Spring、SpringMVC、SpringBoot、SpringCloud 框架常用注解说明 目录 注…

手撕STL——vector

目录 引言 1&#xff0c;了解 STL 中的 vector 2&#xff0c;先来一个简易版跑起来 2_1&#xff0c;构造函数 2_2&#xff0c;扩容reserve&#xff08;&#xff09; 2_3&#xff0c;push_back&#xff08;&#xff09; 2_4&#xff0c;pop_back&#xff08;&#xff09; …

优恩-具备浪涌保护功能的固态继电器UNRD0610-无触点开关器件‌

MOSFET固态继电器 : 最高负载电压&#xff1a;60V 最大负载电流&#xff1a;10A 快速响应时间&#xff1a;≤1ms 低驱动电流&#xff1a;≤10mA 高绝缘性&#xff0c;输入输出间隔离电压&#xff1a;AC3000V 耐脉冲浪涌冲击能力强 符合IEC 61000-4-2 ESD标准&#xff1a…

Kaamel隐私与安全分析报告:Microsoft Recall功能评估与风险控制

本报告对Microsoft最新推出的Recall功能进行了全面隐私与安全分析。Recall是Windows 11 Copilot电脑的专属AI功能&#xff0c;允许用户以自然语言搜索曾在电脑上查看过的内容。该功能在初次发布时因严重隐私和安全问题而备受争议&#xff0c;后经微软全面重新设计。我们的分析表…

Kotlin协程Semaphore withPermit约束并发任务数量

Kotlin协程Semaphore withPermit约束并发任务数量 import kotlinx.coroutines.* import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.launch import kotlinx.coroutines.runBlockingfun main() {val permits 1 /…

鸿蒙语言基础

准备工作 去鸿蒙官网下载开发环境 点击右侧预浏览&#xff0c;刷新和插销按钮&#xff0c;插销表示热更新&#xff0c;常用按钮。 基础语法 string number boolean const常量 数组 let s : string "1111"; console.log("string", s);let n : number …

C++数据结构与二叉树详解

前言&#xff1a; 在C编程的世界里&#xff0c;数据结构是构建高效程序的基石&#xff0c;而二叉树则是其中最优雅且应用广泛的数据结构之一。本文将带你深入理解二叉树的本质、实现与应用&#xff0c;助你在算法设计中游刃有余。 一、二叉树的基本概念 1. 什么是二叉树 二叉树…

浅析数据库面试问题

以下是关于数据库的一些常见面试问题: 一、基础问题 什么是数据库? 数据库是按照数据结构来组织、存储和管理数据的仓库。SQL 和 NoSQL 的区别是什么? SQL 是关系型数据库,使用表结构存储数据;NoSQL 是非关系型数据库,支持多种数据模型(如文档型、键值对型等)。什么是…

piamon实战-- 如何使用 Paimon 的 Java API 实现数据的点查

简介 Apache Paimon(原 Flink Table Store)是一款基于流批一体架构的 ​​高性能数据湖存储框架​​,支持低延迟的数据更新、实时查询和高效的键值点查(Point Lookup)。 本文将深入解析 Paimon 的点查机制,并通过 Java API 代码案例演示如何实现数据的点查功能。 一、Pai…

社交媒体时代的隐私忧虑:聚焦Facebook

在数字化时代&#xff0c;社交媒体平台已成为人们日常生活的重要组成部分。Facebook作为全球最大的社交媒体之一&#xff0c;拥有数十亿用户&#xff0c;其对个人隐私的影响和忧虑也日益凸显。本文将探讨社交媒体时代下&#xff0c;尤其是Facebook平台上的隐私问题。 数据收集…