【Spring篇】IOC/DI注解开发
🍓系列专栏:Spring系列专栏
🍉个人主页:个人主页
目录
一、IOC/DI注解开发
1.注解开发定义bean
2.纯注解开发模式
1.思路分析
2.实现步骤
3.注解开发bean作用范围与生命周期管理
1.环境准备
2.Bean的作用范围
3.Bean的生命周期
4.注解开发依赖注入
1.环境准备
2.注解实现按照类型注入
3.注解实现按照名称注入
4.简单数据类型注入
5.注解读取properties配置文件
二、IOC/DI注解开发管理第三方bean
1.环境准备
2.注解开发管理第三方bean
3.引入外部配置类
1.使用包扫描引入
2.使用@Import引入
4.注解开发实现为第三方bean注入资源
1.简单数据类型
2.引用数据类型
三、注解开发总结
一、IOC/DI注解开发
- 2.0版开始支持注解
- 2.5版注解功能趋于完善3.0版支持纯注解开发
环境准备
在学习注解开发之前,先来准备下案例环境:
- 创建一个Maven项目
- pom.xml添加Spring的依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
- resources下添加applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>
- 添加 BookDao 、 BookDaoImpl 、 BookService 、 BookServiceImpl 类
public interface BookDao {
public void save();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
public interface BookService {
public void save();
}
public class BookServiceImpl implements BookService {
public void save() {
System.out.println("book service save ...");
}
}
- 创建运行类App
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}

1.注解开发定义bean
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
@Component("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}

步骤3:配置Spring的注解包扫描
为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<context:component-scan base-package="com.itheima"/>
</beans>
- component:组件,Spring将管理的bean视作自己的一个组件
- scan:扫描
- 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快
- 包路径越少[如:com.itheima],扫描的范围越大速度越慢
- 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。

@Component
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
步骤6:运行程序
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao);
//按类型获取bean
BookService bookService = ctx.getBean(BookService.class);
System.out.println(bookService);
}
}

- BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象
- @Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取,如
BookService bookService = (BookService)ctx.getBean("bookServiceImpl");
System.out.println(bookService);
对于@Component注解,还衍生出了其他三个注解@Controller、@Service、@Repository
这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?
方便我们后期在编写类的时候能很好的区分出这个类是属于表现层、业务层还是数据层的类。
名称 | @Component/@Controller/@Service/@Repository |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置该类为spring管理的bean |
属性 | value(默认):定义bean的id |
2.纯注解开发模式
- Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道具体如何实现?
1.思路分析
2.实现步骤
public class SpringConfig {
}
@Configuration
public class SpringConfig {
}
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
public class AppForAnnotation {public static void main(String[] args) {//AnnotationConfigApplicationContext加载Spring配置类初始化Spring容器ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = (BookDao) ctx.getBean("bookDao");System.out.println(bookDao);//按类型获取beanBookService bookService = ctx.getBean(BookService.class);System.out.println(bookService);}
}

- Java类替换Spring核心配置文件
- @Configuration注解用于设定当前类为配置类
- @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
@ComponentScan({com.itheima.service","com.itheima.dao"})
- 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象
//加载配置文件初始化容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
//加载配置类初始化容器
ApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
名称 | @Configuration |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置该类为spring配置类 |
属性 | value(默认):定义bean的id |
名称 | @ComponentScan |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置spring配置类扫描路径,用于加载使用注解格式定义的bean |
属性 | value(默认):扫描路径,此路径可以逐层向下扫描 |
- 记住@Component、@Controller、@Service、@Repository这四个注解
- applicationContext.xml中<context:component-san/>的作用是指定扫描包路径,注解为 @ComponentScan
- @Configuration标识该类为配置类,使用类替换applicationContext.xml文件
- ClassPathXmlApplicationContext是加载XML配置文件
- AnnotationConfigApplicationContext是加载配置类
3.注解开发bean作用范围与生命周期管理
1.环境准备
- 创建一个Maven项目
- pom.xml添加Spring的依赖【之前的】
- 添加一个配置类SpringConfig【之前的】
- 添加BookDao、BookDaoImpl类
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
- 创建运行类App
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao1 = ctx.getBean(BookDao.class);
BookDao bookDao2 = ctx.getBean(BookDao.class);
System.out.println(bookDao1);
System.out.println(bookDao2);
}
}

2.Bean的作用范围
(1)先运行App类,在控制台打印两个一摸一样的地址,说明默认情况下bean是单例
(2)要想将BookDaoImpl变成非单例,只需要在其类上添加@scope注解
@Repository
//@Scope设置bean的作用范围
@Scope("prototype")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
知识点:@Scope
名称 | @Scope |
类型 | 类注解 |
位置 | 类定义上方 |
作用 | 设置该类创建对象的作用范围 可用于设置创建出的 bean 是否为单例对象 |
属性 | value (默认):定义 bean 作用范围, 默认值 singleton (单例),可选值 prototype (非单例) |
3.Bean的生命周期
@Repository
//@Scope设置bean的作用范围public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ...");}
// @PostConstruct设置bean的初始化方法@PostConstructpublic void init() {System.out.println("init ...");}//@PreDestroy设置bean的销毁方法@PreDestroypublic void destroy() {System.out.println("destroy ...");}}
public class App {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao1 = ctx.getBean(BookDao.class);BookDao bookDao2 = ctx.getBean(BookDao.class);System.out.println(bookDao1);System.out.println(bookDao2);ctx.close();}
}
运行App,类查看打印结果,证明init和destroy方法都被执行了。

注意:@PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>

小结
4.注解开发依赖注入
Spring为了使用注解简化开发,并没有提供构造函数注入、setter注入对应的注解,只提供了自动装配的注解实现。
1.环境准备
- 创建一个Maven项目
- pom.xml添加Spring的依赖
- 添加一个配置类SpringConfig
- 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}public interface BookService {public void save();}@Servicepublic class BookServiceImpl implements BookService {private BookDao bookDao;public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}public void save() {System.out.println("book service save ...");bookDao.save();}}
- 创建运行类App
public class App {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookService bookService = ctx.getBean(BookService.class);bookService.save();}
}

环境准备好后,运行后会发现有问题
出现问题的原因是,在BookServiceImpl类中添加了BookDao的属性,并提供了setter方法,但是 目前是没有提供配置注入BookDao的,所以bookDao对象为Null,调用其save方法就会报控指针异 常。
2.注解实现按照类型注入
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
// public void setBookDao(BookDao bookDao) {
// this.bookDao = bookDao;
// }
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
- 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
- 普通反射只能获取public修饰的内容
- 暴力反射除了获取public修饰的内容还可以获取private修改的内容
- 所以此处无需提供setter方法
@Repository
public class BookDaoImpl2 implements BookDao {public void save() {System.out.println("book dao save ...2");}
}

此时,按照类型注入就无法区分到底注入哪个对象,解决方案:按照名称注入
@Repository("bookDao")public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ..." + name);}
}@Repository("bookDao2")public class BookDaoImpl2 implements BookDao {public void save() {System.out.println("book dao save ...2");}
}
- @Autowired是按照类型注入的,给BookDao的两个实现起了名称,它还是有两个bean对象, 为什么不报错?
- @Autowired默认按照类型自动装配,如果IOC容器中同类的Bean找到多个,就按照变量名和 Bean的名称匹配。因为变量名叫bookDao而容器中也有一个bookDao,所以可以成功注入。
- 分析下面这种情况是否能完成注入呢?
不行,因为按照类型会找到多个bean对象,此时会按照bookDao名称去找,因为IOC容器只有名称叫bookDao1和bookDao2 ,所以找不到,会报NoUniqueBeanDefinitionException
3.注解实现按照名称注入
@Service
public class BookServiceImpl implements BookService {
@Autowired
@Qualifier("bookDao1")
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
4.简单数据类型注入
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
@Value("itheima")
private String name;
public void save() {
System.out.println("book dao save ..." + name);
}
}
5.注解读取properties配置文件
@Value一般会被用在从properties配置文件中读取内容进行使用,具体如何实现?
name=itheima888
@Configuration
@ComponentScan("com.itheima")
//@PropertySource加载properties配置文件
@PropertySource({"jdbc.properties"})
public class SpringConfig {
}
@Repository("bookDao")public class BookDaoImpl implements BookDao {//@Value:注入简单类型(无需提供set方法)@Value("${name}")private String name;public void save() {System.out.println("book dao save ..." + name);}
}

- 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个
@PropertySource({"jdbc.properties","xxx.properties"})
- @PropertySource注解属性中不支持使用通配符* ,运行会报错
@PropertySource({"*.properties"})
- @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件
@PropertySource({"classpath:jdbc.properties"})

二、IOC/DI注解开发管理第三方bean
1.环境准备
添加BookDao、BookDaoImpl类
public interface BookDao {
public void save();
}
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ..." );
}
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
}
}

2.注解开发管理第三方bean
在上述环境中完成对Druid数据源的管理,具体的实现步骤为:
步骤1:导入对应的jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
@Configuration
public class SpringConfig {
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}

3.引入外部配置类
如果把所有的第三方bean都配置到Spring的配置类SpringConfig中,虽然可以,但是不利于代码阅 读和分类管理,所有我们就想能不能按照类别将这些bean配置到不同的配置类中?
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
1.使用包扫描引入
步骤1:在Spring的配置类上添加包扫描
@Configuration
@ComponentScan("com.itheima.config")
public class SpringConfig {
}
@Configuration
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
2.使用@Import引入
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
@Configuration
//@ComponentScan("com.itheima.config")
@Import({JdbcConfig.class})
public class SpringConfig {
}
注意:
@Configuration
//@ComponentScan("com.itheima.config")
@Import(JdbcConfig.class)
@Import(Xxx.class)
public class SpringConfig {
}
4.注解开发实现为第三方bean注入资源
1.简单数据类型
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
public class JdbcConfig {
private String driver;
private String url;
private String userName;
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
public class JdbcConfig {//1.定义一个方法获得要管理的对象@Value("com.mysql.jdbc.Driver")private String driver;@Value("jdbc:mysql://localhost:3306/spring_db")private String url;@Value("root")private String userName;@Value("root")private String password;//2.添加@Bean,表示当前方法的返回值是一个bean@Beanpublic DataSource dataSource(){DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driver);ds.setUrl(url);ds.setUsername(userName);ds.setPassword(password);return ds;}
}
1.resources 目录下添加 jdbc.properties2. 配置文件中提供四个键值对分别是数据库的四要素3. 使用 @PropertySource 加载 jdbc.properties 配置文件4. 修改 @Value 注解属性的值,将其修改为 ${key} , key 就是键值对中的键的值
2.引用数据类型
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
@Configuration
@ComponentScan("com.itheima.dao")
@Import({JdbcConfig.class})
public class SpringConfig {
}
@Bean
public DataSource dataSource(BookDao bookDao){
System.out.println(bookDao);
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}

三、注解开发总结
相关文章:

【Spring篇】IOC/DI注解开发
🍓系列专栏:Spring系列专栏 🍉个人主页:个人主页 目录 一、IOC/DI注解开发 1.注解开发定义bean 2.纯注解开发模式 1.思路分析 2.实现步骤 3.注解开发bean作用范围与生命周期管理 1.环境准备 2.Bean的作用范围 3.Bean的生命周期 4.注解开发依赖…...
1 Unix基础知识
1.1 登录 1.1 登录名 登录Unix系统时,要先输入登录名,然后再输入口令。系统再其口令文件(/etc/password文件)查看登录名。口令文件中的登录项由7个以冒号分隔的字段组成:登录名,加密口令,数字用…...

【翻译一下官方文档】认识uniCloud云数据库(基础篇)
我将用图文的形式,把市面上优质的课程加以自己的理解,详细的把:创建一个uniCloud的应用,其中的每一步记录出来,方便大家写项目中,做到哪一步不会了,可以轻松翻看文章进行查阅。(此文…...
全局解释器锁 GIL
问题 你已经听说过全局解释器锁 GIL,担心它会影响到多线程程序的执行性能。 解决方案 尽管 Python 完全支持多线程编程,但是解释器的 C 语言实现部分在完全并行执行时并不是线程安全的。 实际上,解释器被一个全局解释器锁保护着ÿ…...
github 下载文件加速 https://moeyy.cn/gh-proxy/
GitHub文件链接带不带协议头都可以,支持release、archive以及文件,右键复制出来的链接都是符合标准的。 注意,不支持项目文件夹,请使用Git。 分支源码:https://github.moeyy.xyz/https://github.com/moeyy/project/arc…...

第五章 资源包使用
游戏开发中会大量使用模型文件,图片文件,这些资源都需要事先导入到项目中去。导入的方式非常简单,将这些文件直接复制到项目中的Assets目录下即可。Unity 会在文件添加到 Assets 文件夹时自动检测到这些文件并同步显示在Project视图中。 Uni…...
Linux od命令
Linux od命令用于输出文件内容。 od指令会读取所给予的文件的内容,并将其内容以八进制字码呈现出来。 语法 od [-abcdfhilovx][-A <字码基数>][-j <字符数目>][-N <字符数目>][-s <字符串字符数>][-t <输出格式>][-w <每列字符…...

【15】SCI易中期刊推荐——电子电气 | 仪器仪表(中科院4区)
💖💖>>>加勒比海带<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉 | 深度学习Tr…...
基于PaddleServing的串联部署 ocr 识别模型
要点: 使用paddleserving服务 1 首先需要安装PaddleServing部署相关的环境 PaddleServing是PaddlePaddle推出的一种高性能、易扩展、高可用的机器学习服务框架。PaddleOCR中使用PaddleServing主要是为了将训练好的OCR模型部署到线上环境,提供API服务&a…...
java OutputStream学习
1.概要 OutputStream位于java.io,它在Java 实现的IO类库中是一个很基础的抽象类。在层级上,是所有字节输出流类的父类,在功能上,表示接受字节并把它们输出。 2.实现类及子类简介 OutputStream有诸多子类: ByteAr…...
java 上传文件生成二进制流文件
最近在项目中遇到一个问题:需要将上传的文件生成输出流,然后将输出流转换为输入流上传到oss。 -------------------------------------------导出代码实现---------------------------------------------------------- ByteArrayOutputStream baos nu…...
质量小议22 -- 多少分合适
60分万岁~???!!! 如果用分数评价质量,多少分合适?60,70,80...还是100,或者 120 对于质量的提升,是雪中送炭,还是锦上添…...
变频器参数设定说明
使用默贝克MT110-0R4-S2B实现下面的练习题: 1、先恢复出厂设置,再输入电机参数,选择静态调谐 2、两种运行模式:多段速(8段)和简易PLC(4段) 3、面板启停,运行模式通过外部…...

实用调试技巧
目录: 1.什么是bug? 2.调试是什么?有多重要? 3.debug和release的介绍 4.Windows环境调试介绍 5.一些调试的实例 6.如何写出好(易于调试)的代码 7.编程常见的错误 1.什么是bug? bug--->臭虫、虫子。 为什么含…...

谁是液冷行业真龙头?疯狂的液冷技术!
“人工智能领域AIGC”、“ChatGPT”、“数据特区”、“东数西算”、“数据中心”,可以说是2023年最热的概念,算力提升的背后,处理器的功耗越来越高,想发挥出处理器的最高性能,需要更高的散热效率。 算力井喷之下&…...

自动化运维工具之Ansible
目录 一、自动化运维 1、通过xshell自动化运维 2、Ansible简介 3、Ansible特点及优势 4、Ansible核心程序 5、Ansible工作原理及流程 6、部署Ansible自动化运维工具 7、Ansible常用模块 (1) ansible命令行模块 (2) command模块 (3) shell模块 (4) cron模块 (5) us…...

霍兰德人格分析雷达图
雷达图 Radar Chart 雷达图是多特性直观展示的重要方式 问题分析 霍兰德认为:人格兴趣与职业之间应有一种内在的对应关系 人格分类:研究型、艺术型、社会型、企业型、传统型、现实性 职业:工程师、实验员、艺术家、推销员、记事员、社会工…...

《Odoo开发者模式必知必会》—— 缘起
Odoo作为业界优秀的开源商务软件,在全球范围内拥有广泛的使用者。在领英国际,可以搜索到全球很多国家都有大量odoo人才需求的招聘信息。在国内,虽然已经有为数不少的企业,他们或者已经使用odoo,或者正在了解odoo&#…...
Java8的Options介绍
Java8引入了一个名为 Options 的新类,它是一个容器,可以保存单个值或根本不保存任何值。Optional目的是提供一种更优雅的方式来处理 null 值,这通常会导致NullPointerException。在这篇博客文章中,我们将探索如何在 Java8中使用 O…...

SpringBoot 多数据源及事务解决方案
1. 背景 一个主库和N个应用库的数据源,并且会同时操作主库和应用库的数据,需要解决以下两个问题: 如何动态管理多个数据源以及切换? 如何保证多数据源场景下的数据一致性(事务)? 本文主要探讨这两个问题的解决方案…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...