1、springboot中的starter,如果要我自定义写一个,怎么去实现
-
新建项目:新建一个Maven项目。
-
添加依赖:在
pom.xml
中添加必要的Spring Boot依赖,通常你会需要spring-boot-starter
作为基础。 -
编写自定义代码:你可以添加自定义的Beans、配置类、属性文件等。
-
提供默认配置:在
resources
目录下的META-INF
中创建一个spring.factories
文件,然后在这个文件中指定你的自定义auto-configuration类。例如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yourpackage.YourAutoConfiguration
-
打包:将项目打包成jar文件。
-
使用starter:在其他项目中,你可以将此starter作为依赖来使用。
2、springboot里的容器了解哪些
-
BeanFactory:是最简单的容器,为DI(依赖注入)提供了支持,它使用
BeanDefinition
对象来管理和创建bean。 -
ApplicationContext:是
BeanFactory
的超集,在Spring应用程序中,它被用作核心的容器接口。ApplicationContext
提供了更多的企业级功能,如事件发布、国际化处理等。- AnnotationConfigApplicationContext:从一个或多个Java配置类中加载Spring应用上下文。
- ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类路径资源。
- FileSystemXmlApplicationContext:从文件系统的XML配置文件中加载上下文定义。
-
WebApplicationContext:一个特定于Web应用程序的
ApplicationContext
,为Web应用程序提供了一些额外的特性。 -
Lifecycle and Phases:Spring容器也管理bean的生命周期和各种生命周期回调,从创建到销毁。例如,
@PostConstruct
和@PreDestroy
注解等。 -
Environment Abstraction:Spring容器提供了一个
Environment
接口,它表示当前应用程序运行的环境。这为我们提供了一个方便的方法来访问环境特定的属性。、
3、volatile和sychronized关键字
volatile:
volatile
是Java中的一个类型修饰符,它用于声明一个变量为"易变"的。- 它确保对变量的读写都是直接与主内存进行的,而不是先在工作内存中处理然后再同步到主内存。
- 使用
volatile
关键字声明的变量,其修改会立即对其他线程可见。 - 它可以确保变量的可见性,但不能保证复合操作的原子性。
synchronized:
synchronized
是Java中的一个关键字,用于指定一个块是同步的。- 它可以确保同一时刻只有一个线程可以执行同步块中的代码,从而避免多线程之间的争用情况。
- 使用
synchronized
可以确保方法或块中的代码的原子性。 - 与
volatile
相比,synchronized
的开销更大,因为它涉及到锁的获取和释放。
4、读屏障和写屏障
在Java中,JMM(Java Memory Model)为了确保不同线程之间的可见性,有时需要添加特定的屏障或指令。
读屏障(Load Barrier):
- 确保在屏障之前的读操作不会被重排序到屏障之后。
写屏障(Store Barrier):
- 确保在屏障之前的写操作不会被重排序到屏障之后。
这些屏障确保了内存的一致性和可见性。
5、AQS以及可重入锁
AQS(AbstractQueuedSynchronizer):
- AQS是Java并发包中的一个框架,用于构建锁、同步器和其他并发控制工具。
- 它使用一个int成员变量来表示同步状态,并使用一个FIFO队列来管理等待线程。
- AQS提供了模板方法来使用和修改同步状态,子类可以覆盖这些方法来实现自己的同步机制。
可重入锁(ReentrantLock):
- 是Java并发包中的一个类,它实现了
Lock
接口,提供了与synchronized
类似的同步能力,但是功能更加强大。 - 它允许一个线程多次获取同一个锁,这就是所谓的"重入"功能。
- 可重入锁除了可以实现基本的锁功能外,还提供了其他高级功能,如:可以被中断的锁获取、超时锁获取、公平锁等。
- ReentrantLock内部使用AQS实现其同步控制。
6、git常用操作
设置和初始化:
git config --global user.name "Your Name" # 设置全局用户名
git config --global user.email "your@email.com" # 设置全局用户邮箱
git init # 初始化新的Git仓库
基本操作:
git clone [URL] # 从URL克隆一个仓库到本地
git status # 查看工作目录的状态(修改的文件、未追踪的文件等)
git add [filename] # 将指定文件添加到暂存区
git add . # 将所有变更添加到暂存区
git commit -m "Commit message" # 将暂存区的内容提交到仓库,并附加消息
分支操作:
git branch # 列出本地的所有分支
git branch [branch-name] # 创建一个新的分支
git checkout [branch-name] # 切换到指定分支
git checkout -b [branch-name] # 创建新分支并立即切换到这个分支
git merge [branch-name] # 将指定分支合并到当前分支
远程操作:
git remote -v # 查看所有远程仓库
git remote add [alias] [URL] # 添加新的远程仓库,并给它一个别名
git fetch [remote-name] # 从远程仓库下载对象和refs
git pull [remote-name] [branch-name] # 从远程获取数据并尝试合并到当前分支
git push [remote-name] [branch-name] # 将分支推送到远程仓库
查看历史:
git log # 查看提交历史
git log --oneline # 以一行的形式查看简洁的提交历史
撤销操作:
git checkout -- [filename] # 恢复工作目录中指定文件的修改
git reset HEAD [filename] # 从暂存区中撤销指定文件的变更
git reset [commit-hash] # 将HEAD和当前分支指向指定的提交
7、dubbo的架构
-
提供者(Provider):
- 服务提供方,它向注册中心注册其提供的服务。
-
消费者(Consumer):
- 服务消费方,它从注册中心订阅所需的服务,并从提供者那里调用服务。
-
注册中心(Registry):
- 服务注册与发现的中心。提供者在启动时向注册中心注册,并且消费者可以从注册中心查询到所需的服务。
-
监控中心(Monitor):
- 对Dubbo服务进行监控的中心,记录服务的调用次数、调用时长等统计信息。
-
调用关系说明:
- 消费者和提供者在启动时都会与注册中心建立长连接,方便注册服务或者订阅服务。
- 消费者从注册中心订阅服务时,注册中心会返回提供者的地址。消费者直接和提供者建立连接,并进行服务调用。
- 监控中心定时从提供者或消费者收集统计信息。
8、数据库的如何分库分表
分库分表是在大数据量情况下,为了提高数据库的性能和扩展性而采取的策略。其主要目的是将大表或大库分成更小、更容易管理的块。
-
垂直分表:
- 按照业务功能,将一个大表分成几个小表。例如,一个用户信息表可以分为用户基本信息表、用户登录信息表、用户偏好设置表等。
-
水平分表:
- 将一个表按照某种规则(如范围、哈希、目录)分成多个表。例如,用户表可以按照用户ID的范围分成多个表。
-
分库:
- 将数据从一个数据库分到多个数据库实例。这可以是垂直分库,也可以是水平分库。
-
分片策略:
- 常见的分片策略有范围分片、哈希分片和目录分片。
-
中间件:
- 为了方便管理和查询分库分表后的数据,通常会使用一些中间件,如ShardingSphere、Mycat等。
9、慢查询(有子查询或者各种连接情况)如何优化
针对有子查询或各种连接情况的慢查询,以下是一些建议的优化方法:
-
避免使用子查询:尽量使用连接(JOIN)替代子查询。
-
优化JOIN:
- 使用适当的索引。
- 保证连接条件中的字段在两个表中的数据类型一致。
- 尽量减少JOIN的表的数量。
-
使用EXPLAIN:使用EXPLAIN命令查看查询的执行计划,从中找到慢的部分并进行优化。
-
**避免SELECT * **:只选择需要的字段。
-
使用合适的索引:确保查询条件中的字段有索引,并且是最优的。
-
优化数据结构:如使用更合适的数据类型,规范化数据结构等。
-
避免使用函数和复杂的算法:这样可以减少计算的开销。
-
调整查询缓存:对于经常查询并且不常变化的数据,可以使用查询缓存。
-
分析并优化硬件和系统配置:如增加内存、优化磁盘I/O、调整数据库配置等。