Spring框架中的Bean是线程安全的吗?如果线程不安全,那么该如何处理?
一般spring bean都是无状态的,也就不存在什么线程安全问题,除非你在bean中存储数据让其他线程可以感知,自然就有了线程安全问题,处理方式可以使用 ThreadLocal、synchronize、aqs都可以,什么场景能用到的话,例如使用本地缓存分摊并发流量之类的,使用chm或者guava cache都能保证线程安全问题
spring 中的 bean 是单例还是多例?
在 Spring 中,默认情况下,bean
是 单例(singleton) 的,即 Spring 容器在启动时会创建一个共享的 bean
实例,并且每次请求都会返回这个实例。然而,Spring 也支持通过配置将 bean
定义为 多例(prototype),这样每次请求都会返回一个新的 bean
实例。
依赖倒置,依赖注入,控制反转分别是什么?
- 控制反转:框架控制程序的执行流程
- 依赖注入: 将一个类所需的外部依赖(组件、服务)由外部容器或调用者负责创建并注入,而不是在类内部自行构建,实现了反转控制、松耦合和高可测试性。
- 依赖倒置:高层模块不依赖低层模块,它们共同依赖于同一个抽象。抽象不需要依赖具体的实现细节,具体实现细节依赖抽象
依赖注入的注入方式?3个(待理解)
- 构造器注入(Constructor Injection)
- Setter 注入(Setter Injection)
- 接口注入(Interface Injection)
详细:
1. 构造器注入(Constructor Injection)
构造器注入是通过构造函数传入依赖对象。它是一种强制性依赖注入方式,即依赖对象在类的构造过程中必须被注入。
示例代码:
// 定义接口
interface Service {
void serve();
}
// 实现类
class ServiceImpl implements Service {
public void serve() {
System.out.println("Service is serving...");
}
}
// 客户端类依赖 Service
class Client {
private Service service;
// 通过构造器注入依赖
public Client(Service service) {
this.service = service;
}
public void doWork() {
service.serve();
}
}
public class Main {
public static void main(String[] args) {
// 手动注入
Service service = new ServiceImpl();
Client client = new Client(service);
client.doWork();
}
}
在这个例子中,Client
类依赖于 Service
接口的实现类。依赖注入通过构造器实现,Client
的构造函数需要一个 Service
对象。
2. Setter 注入(Setter Injection)
Setter 注入是通过 setter 方法来注入依赖对象。这种方式较为灵活,可以在对象创建之后随时修改依赖对象。
示例代码:
// 定义接口
interface Service {
void serve();
}
// 实现类
class ServiceImpl implements Service {
public void serve() {
System.out.println("Service is serving...");
}
}
// 客户端类依赖 Service
class Client {
private Service service;
// Setter 方法注入
public void setService(Service service) {
this.service = service;
}
public void doWork() {
service.serve();
}
}
public class Main {
public static void main(String[] args) {
// 手动注入
Service service = new ServiceImpl();
Client client = new Client();
client.setService(service); // 通过 setter 注入依赖
client.doWork();
}
}
在这个例子中,Client
类的依赖 Service
通过 setService()
方法注入。
3. 接口注入(Interface Injection)
接口注入通过让类实现一个接口,然后通过该接口注入依赖。这个方式在 Java 中较为少见,在一些特定的框架中可能会用到。
4. Spring 框架中的依赖注入
在现代 Java 开发中,最常见的依赖注入实现是通过 Spring Framework 来实现的。Spring 提供了强大的 IoC 容器和注解支持,可以轻松实现依赖注入。
使用注解的方式:
Spring 通过注解来简化依赖注入的配置,常见的注解有:
@Autowired
:自动注入依赖。@Component
:标记一个类为 Spring 管理的组件。@Service
,@Repository
,@Controller
:这些是@Component
的特定化注解,用于分别表示服务层、持久层和控制层。
示例代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
interface Service {
void serve();
}
@Component
class ServiceImpl implements Service {
public void serve() {
System.out.println("Service is serving...");
}
}
@Component
class Client {
private Service service;
// 通过构造器注入
@Autowired
public Client(Service service) {
this.service = service;
}
public void doWork() {
service.serve();
}
}
public class Main {
public static void main(String[] args) {
// 使用 Spring 的 ApplicationContext 获取 Bean
org.springframework.context.ApplicationContext context =
new org.springframework.context.annotation.AnnotationConfigApplicationContext(Main.class);
// 获取 Client Bean 并调用方法
Client client = context.getBean(Client.class);
client.doWork();
}
}
在这个例子中:
@Component
注解标记了ServiceImpl
和Client
类,告诉 Spring 容器这两个类是需要管理的组件。@Autowired
注解自动注入Service
实例到Client
中。Spring 会自动寻找类型匹配的Service
实现类(即ServiceImpl
)并注入。ApplicationContext
会创建Client
和ServiceImpl
的实例,并且自动注入依赖。
5. XML 配置方式
除了注解方式,Spring 还可以通过 XML 配置文件来实现依赖注入。这种方式已经被现代的注解方式所替代,但在一些旧版本的 Spring 项目中仍然存在。
示例代码:
<!-- Spring XML 配置 -->
<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="service" class="com.example.ServiceImpl"/>
<bean id="client" class="com.example.Client">
<constructor-arg ref="service"/>
</bean>
</beans>
在这个配置文件中,Spring 容器会创建 ServiceImpl
和 Client
实例,并通过构造器注入将 ServiceImpl
注入到 Client
中。
SpringBoot
SpirngBoot和SpirngMVC的区别?
Spring MVC 是基于 Spring 框架的一个模块,提供了一种 Model-View-Controller(模型-视图-控制器)的开发模式。
Spring Boot 旨在简化 Spring 应用的配置和部署过程,提供了大量的自动配置选项,以及运行时环境的内嵌 Web 服务器,这样就可以更快速地开发一个 SpringMVC 的 Web 项目。
Spring MVC
MVC分层介绍一下?(对于理解项目有帮助)
模型-视图-控制器。软件设计典范,业务逻辑,数据,界面显示分离。
模型:存储数据的对象orPOJO。两类,数据承载Bean(实体类,如User类) or 业务处理Bean(Service 或 Dao对象)。
控制器:用户的请求转发给model,再给用户提供响应。使视图与模型分离。
了解SpringMVC的处理流程吗?
用户到前端控制器到处理映射器,返回执行链,请求适配器,请求Controller处理,请求视图解析器,返回
视图渲染,返回给用户
围绕前端控制器。依次向处理映射器,处理适配器,处理适配器更深到控制器,再视图解析器,最后生成视图给用户
MysBatis
与传统JDBC相比,MyBatis的优点?
基于sql编程,灵活,不影响应用程序或数据库设计,在xml中,降低耦合,便于统一管理。
消除JDBC代码冗余,不需要手动关闭连接
与spring很好集成,开发效率高
提供映射标签,支持对象与数据库的ORM字段关系映射
Spring Cloud
★怎么理解微服务?
了解Spring Cloud吗?说说它和SpringBoot的区别?
Springboot 构建单个spring程序的框架。SpringCloud是构建分布式系统中微服务的架构。
支持限流,熔断降级,网关,服务注册与发现,负载均衡。
用过哪些微服务组件?
注册中心:nacos 负载均衡:nacos API服务网关:gateway 服务保护 :sentinel
什么是负载均衡?
负载均衡(LoadBalancing)是一种技术和策略,用于在多台服务器之间分配传入的网络请求,以平衡服务器负载,提高性能和可靠性。负载均衡可以确保每台服务器都能够充分利用其资源,避免某些服务器过载而导致性能下降或服务不可用。
负载均衡的算法有哪些?
- 简短轮询:请求按顺序发给服务器,不管服务器性能、负载
- 加权轮询:根据服务器性能设置权重,根据权重转发请求,让高性能服务器处理更多请求
- 简单随机:随机发送请求
- 加权随机:
- 一致性哈希:根据用户id或请求参数得到哈希值,映射到对应服务器。保证用户每次使用一台服务器
- 最小活跃数:统计各服务器正在处理的请求数量。把请求发给最闲的
如何实现一直均衡给一个用户?
一致性哈希算法