目录
- 1、为什么要用Spring框架?
- 2、有了spring为什么又出现了 springboot?
- 3、springboot出现后为什么又出现了spring cloud?
- 4、SpringBoot自动配置(重点)
- 5、SpringBoot启动流程(重点)
- 6、简单谈一下你对spring IOC 跟 AOP 的理解吗?
- 7、AOP 有哪些实现方式?都有哪些区别?
- 8、在项目中有没有用到过AOP?比如说你在你以前有没有在哪些场景都用到过AOP?
- 9、spring bean的生命周期?
- 10、spring 中的 bean 它是线程安全的吗?
- 11、spring中事务?失效场景?
- 12、bean factory 跟 factory bean 有什么区别?
- 13、spring 中的循环依赖的问题?怎么解决的?
- 14、SpringBoot 有哪些核心注解?
- 15、你觉得 spring boot 对于 spring 来说它最大的好处是什么?
- 16、在Controller层有一个@PostMapping接口,但是没有加@RequestBody注解,怎样传参可以拿到参数?
- 17、Spring MVC 的执行流程?
- 18、Spring MVC 中常用的注解?
- 19、spring源码中用到了哪些设计模式,详细说明每种设计模式用到的场景?
- 20、Spring中注入bean有几种方式?
- 21、SPI机制是什么,和Spring自动配置有啥关系
- 22、spring 自动配置 和自动装配区别
- 23、spring bean 的线程池模型
- 24、Component 注解跟 bean 注解它有什么区别?
1、为什么要用Spring框架?
- 轻量级:Spring框架本身是轻量级的,不依赖于任何应用服务器,这意味着可以在独立的容器中运行,减少了部署和维护的成本,同时提高了应用的灵活性。
- 提高代码重用性/低耦合性:Spring框架提供了许多模块化的功能,例如AOP、事务管理、数据访问等,这些模块可以被不同的模块或应用程序共享和重用,极大地提高了代码的重用性。
- 易维护性:Spring框架鼓励面向接口编程,通过依赖注入的方式管理对象之间的关系,使得应用程序更加松耦合,代码更易于维护和扩展。
- 测试性:由于依赖注入和面向接口编程的利器,使用Spring框架可以更容易地编写单元测试和集成测试,使得程序的测试覆盖率更高,代码更加健壮可靠。
- 依赖注入:Spring框架的依赖注入机制可以帮助开发人员管理对象之间的依赖关系,进而降低了类与类之间的耦合度,提高了代码的灵活性和可维护性。
2、有了spring为什么又出现了 springboot?
Spring Boot的出现是为了进一步简化Spring应用程序的开发和部署。尽管Spring框架提供了许多功能,但是构建和配置Spring应用程序仍然需要进行大量的手动工作。Spring Boot的出现解决了这些问题,并带来了以下几个重要优势:
- 简化配置:Spring Boot采用约定优于配置的原则,内置了许多默认配置,极大地简化了应用程序的配置过程,开发者只需关注自己的业务逻辑即可。
- 快速启动:Spring Boot提供了嵌入式的Tomcat、Jetty等容器,可以快速创建可运行的独立应用程序,无需手动部署到外部服务器。
- 自动化:Spring Boot提供了自动配置和自动化的功能,例如自动配置数据源、事务管理等,减少了繁琐的手动配置步骤。
- 监控和管理:Spring Boot提供了诸如健康检查、指标收集等监控和管理功能,使得应用程序更易于监控和管理。
- 微服务支持:Spring Boot对构建微服务应用程序提供了良好的支持,例如通过Spring Cloud可以轻松实现服务注册、配置管理、负载均衡等功能。
3、springboot出现后为什么又出现了spring cloud?
- 服务治理:随着微服务架构的兴起,服务的数量和复杂性不断增加。Spring Cloud提供了服务注册与发现的功能,通过服务注册中心来管理和发现各个微服务的实例,简化了服务之间的调用和协作。
- 负载均衡:在微服务架构中,服务实例的数量可能会动态变化,需要能够根据请求量和服务实例的使用情况进行负载均衡。Spring Cloud 提供了集成 Ribbon,Feign 等工具来实现负载均衡的功能。
- 断路器:在分布式系统中,服务之间的调用是不可靠的,可能会因为网络故障、服务故障等原因导致调用失败。Spring Cloud提供了集成Hystrix的断路器模式,可以实现服务之间的容错处理和自动降级。
- 分布式配置:在分布式系统中,配置管理也是一个重要的问题。Spring Cloud提供了集成Config Server的功能,可以实现统一的分布式配置管理,并且支持配置的动态刷新。
- 监控和追踪:在分布式系统中,对系统进行监控、追踪和日志记录非常重要。Spring Cloud提供了集成Sleuth和 Zipkin 的功能,帮助开发人员实现分布式跟踪,并提供了监控和日志记录的能力。
4、SpringBoot自动配置(重点)
简单版:
就是随着A项目的启动,会扫描到主启动类上的@SpringBootApplication注解
该注解里面存在一个@EnableAutoConfiguration注解
在EnableAutoConfiguration注解里面又存在一个Import注解
执行selectImports方法,selectImports返回的是配置类的全路径名
配置类从何而来,是基于SPI机制,去classpath下的META-INF目录下找所有的spring.factories文件,然后将所有的spring.factories文件进行解析
自动将我所需要的Bean对象注入到IoC容器里面去,@Configuration和@Bean,自动体现在我没有对任何类加前面的两个注解。
细节版:
SpringBoot的自动配置原理:在SpringBoot项目中都会有一起启动类上贴有一个注解叫@SpringBootApplication,这个注解是一个复合注解,里面有几个注解,分别是:@ComponentScan,@SpringBootConfiguration,@EnableAutoConfiguration。
- @ComponentScan 主要让启动类赋予扫描功能,做到扫描包路径
- @SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类。
- @EnableAutoConfiguration这也是自动配置的主要注解也是一个复合注解,主要有两个注解@AutoConfigurationPackage和@Import
- @AutoConfigurationPackage: 该注解的作用是向容器内注入一个组件,组件的作用是保存一些包路径
- 真正的核心@Import:在@import注解中导入一个类叫AutoConfigurationImportSelector这个类中有一个方法叫selectImports会返回一个字符串数组,这些字符串都是类的全路径名,这些类的全路径都会被Spring通过反射的方式放到 ioc 容器中交给Spring管理。
- 这些类的全路径名主要都是存放在resource/META-INF/spring.factories中里面存放的数据都是以key,value的形式储存,其中只要找到一个key为EnableAutoContiguration下的value都是类的全路径。通过Spring提供的API SpringFactoriesLoader类的loadFactoryNames方法等等配合@import注解把字符串反射到 ioc 容器中,这些类中标记有Configuration和@Bean的都会加载到Ioc容器中完成自动装配,但是并不是所有的配置类都会加载进去,他会通过@ConditionOnXxxx一系列条件注解进行过滤选择性的加载,不满足就被过滤掉。
5、SpringBoot启动流程(重点)
简单版:
- 首先从main找到run()方法,在执行run()方法之前new一个SpringApplication对象
- 进入run()方法,创建应用监听器SpringApplicationRunListeners开始监听
- 然后加载SpringBoot配置环境(ConfigurableEnvironment),然后把配置环境(Environment)加入监听对象中
- 然后加载应用上下文(ConfigurableApplicationContext),当做run方法的返回对象
- 最后创建Spring容器,refreshContext(context),实现starter自动化配置和bean的实例化等工作。
细节版
- List item
- List item
6、简单谈一下你对spring IOC 跟 AOP 的理解吗?
推荐参考:深入理解Spring框架的IoC、DI和AOP
Spring IOC(控制反转): IOC 是 Spring 框架的核心概念之一,它通过将应用程序的控制权交给容器来管理对象之间的依赖关系。在 IOC 容器的帮助下,开发者不再需要手动地创建和管理对象之间的关联,而是通过配置文件或注解的方式告诉容器如何创建和组装对象。这种松耦合的设计使得应用更加灵活、可测试,同时也方便了组件的替换和升级。
Spring AOP(面向切面编程): AOP 是 Spring 框架中的另一个重要特性,它允许开发者将横切关注点(比如日志、事务管理)与应用程序的主要业务逻辑分离出来,然后通过各种方式(包括注解和配置)将这些关注点模块化,以便在需要时将其应用到应用程序中。Spring AOP 基于代理模式和动态代理技术实现,它有助于减少代码重复性,提高可维护性,并且使得应用的关注点分离更加清晰。
7、AOP 有哪些实现方式?都有哪些区别?
JDK动态代理和Cglib动态代理。在spring中如果实现了接口默认使用JDK动态代理,反之使用Cglib动态代理。
JDK动态代理:
- 目标类必须实现接口,因为代理类直接实现目标类所实现的接口
- JDK内部直接生成
- 通过反射调用目标类
Cglib动态代理:
- 目标类不能有final,因为代理类是继承的目标类
- 第三方ASM生成
- 通过子类调用父类方式
8、在项目中有没有用到过AOP?比如说你在你以前有没有在哪些场景都用到过AOP?
日志记录: 在方法执行前后记录日志,包括方法的输入参数、返回值等信息。
性能监控: 统计方法的执行时间,帮助进行性能分析。
事务管理: 在方法执行前后进行事务的开启、提交或回滚。
安全检查: 检查用户的权限是否满足方法的调用要求。
异常处理: 统一处理方法中的异常,进行统一的异常日志记录或处理。
9、spring bean的生命周期?
- 实例化(Instantiation):Spring 容器根据配置文件或注解来创建 Bean 的实例。
- 属性赋值(Populate properties):Spring 容器将依赖注入或者通过配置文件中的属性来设置 Bean 的属性值。
- 初始化(Initialization):
a. 如果 Bean 实现了 InitializingBean 接口,Spring 将调用其 afterPropertiesSet() 方法。
b. 如果 Bean 使用了 init-method 属性指定了初始化方法,Spring 将调用指定的初始化方法。 - 使用(Bean use):此时 Bean 已经被完全初始化,可以被应用程序使用了。
- 销毁(Destruction):
a. 如果 Bean 实现了 DisposableBean 接口,Spring 容器在 Bean 销毁前会调用其 destroy() 方法。
b. 如果 Bean 使用了 destroy-method 属性指定了销毁方法,Spring 容器将调用指定的销毁方法。
10、spring 中的 bean 它是线程安全的吗?
Spring 容器默认会将 Bean 配置为单例模式,也就是说在默认情况下,Spring 容器会为每个 Bean 创建唯一的实例,这意味着这个实例会被多个线程共享,不是线程安全的,因此需要开发者来确保 Bean 的线程安全性。
如果开发者需要在多线程环境下使用 Bean,需要确保 Bean 的状态是线程安全的,或者通过配置来确保每个线程都有自己的 Bean 实例。这通常可以通过在 Bean 的定义中设置作用域为 prototype 来实现。
11、spring中事务?失效场景?
推荐参考:Spring声明式事务@Transactional
12、bean factory 跟 factory bean 有什么区别?
Bean Factory:
- Bean Factory 是 Spring Framework 中核心的接口之一,它是用来管理 Bean对象的工厂接口。
- BeanFactory 提供了获取 Bean 实例、管理 Bean 的生命周期、依赖注入等功能。
- BeanFactory 是 Spring 框架中最基本的 Bean 容器,负责加载、配置和管理 Bean 对象。
Factory Bean:
- Factory Bean 是一个特殊的 Bean,它实现了org.springframework.beans.factory.FactoryBean接口。
- 这个接口允许定制化的 Bean 实例化过程,提供了一种更加灵活的方式来创建 Bean 实例。
- 通过实现FactoryBean接口,开发者可以定义自定义逻辑来决定要返回的 Bean 实例,从而实现更加复杂的 Bean 的创建和初始化逻辑。
因此,总体来说,Bean Factory 是 Spring Framework 中用于管理 Bean 的核心接口,而 Factory Bean 是一个特殊类型的 Bean,它允许开发者更加灵活地定义 Bean 的创建过程。
13、spring 中的循环依赖的问题?怎么解决的?
推荐参考:深入了解Spring循环依赖和三级缓存机制
14、SpringBoot 有哪些核心注解?
@SpringBootApplication:
这是一个复合注解,用于标注Spring Boot应用的启动类。它整合了多个注解,包括 @Configuration、@EnableAutoConfiguration 和 @ComponentScan。
@RestController:
用于定义RESTful风格的控制器(Controller),通常用于返回JSON等数据。
@RequestMapping:
用于将HTTP请求映射到控制器的处理方法上,可用于类或方法级别。
@Autowired:
用于自动装配Bean,通过类型匹配进行依赖注入。
@ComponentScan:
用于指定Spring在哪些包中寻找组件(Component),这样在包及其子包中的类就会被注册为Bean。
@Configuration:
用于定义配置类,通常与@Bean配合使用,将方法的返回对象注册为Bean。
@EnableAutoConfiguration:
开启Spring Boot的自动配置功能,可以根据项目的依赖情况自动配置Spring应用。
@Value:
用于注入外部配置文件中的值到Bean属性中。
@Component:
通用的注解,可用于组件扫描和自动装配Bean。
15、你觉得 spring boot 对于 spring 来说它最大的好处是什么?
Spring Boot特点:约定大于配置,自动配置、内嵌容器(tomcat)、微服务支持。
Spring Boot优势:简化了开发流程,减少了配置代码。这使得开发者能够更专注于业务逻辑的实现,极大地提高了开发效率。
16、在Controller层有一个@PostMapping接口,但是没有加@RequestBody注解,怎样传参可以拿到参数?
直接在路径的问号后面传参,比如/user/getUser?name=‘王强’
17、Spring MVC 的执行流程?
请求到达前端控制器(DispatcherServlet): 客户端的请求首先到达前端控制器,即DispatcherServlet。
处理器映射器(HandlerMapping)的执行: 前端控制器将根据请求信息调用处理器映射器,处理器映射器将根据请求的URL映射到相应的处理器(Controller)。
处理器适配器(HandlerAdapter)的执行: 处理器映射器将根据请求找到适当的处理器,并调用处理器适配器来执行处理器。
处理器(Controller)的执行: 处理器适配器将调用实际的处理器(Controller)来处理请求,处理器将执行业务逻辑,并返回一个模型与视图对象。
视图解析器(ViewResolver)的执行: 处理器处理完请求后,会返回一个逻辑视图名,前端控制器将调用视图解析器来映射逻辑视图名到具体的视图。
视图渲染: 视图解析器将会把逻辑视图名解析为真正的视图对象,最终前端控制器将会把模型数据传递给视图进行渲染。
响应返回客户端: 渲染后的视图最终会返回给前端控制器,前端控制器会将其显示给客户端。
18、Spring MVC 中常用的注解?
@Controller: 用于标识一个类为 Spring MVC 的控制器,处理客户端请求。
@RequestMapping: 用于将HTTP请求映射到控制器的处理方法,并可以指定请求的URL路径、HTTP方法等。
@GetMapping/@PostMapping/@PutMapping/@DeleteMapping: 这些注解用于指定特定请求类型的映射,例如 @GetMapping 用于处理 GET 请求,@PostMapping 用于处理 POST 请求,以此类推。
@PathVariable: 用于将请求URL中的模板变量绑定到处理方法的参数上。
@RequestParam: 用于将请求参数绑定到处理方法的参数上,还可以指定参数的默认值、是否必须等。
@ModelAttribute: 用于将一个方法返回的对象添加到模型中,使其在视图中可用。
@ResponseBody: 用于指示方法返回的对象应该直接写入 HTTP 响应体中,而不是解析为视图。
@ResponseStatus: 用于指定处理方法的响应状态码。
19、spring源码中用到了哪些设计模式,详细说明每种设计模式用到的场景?
工厂模式(Factory Pattern):
场景: Spring 中 Bean 的创建和管理过程使用了工厂模式,通过 BeanFactory 和 ApplicationContext 接口来创建和管理 Bean。
举例: ApplicationContext 接口的实现类 ClassPathXmlApplicationContext 通过解析 XML 配置文件来实例化Bean,这就是工厂模式的应用。
单例模式(Singleton Pattern):
场景: Spring 中的 Bean 默认为单例,Spring 容器中每一个 Bean 默认只会创建一个实例。
举例: 当我们通过 ApplicationContext 获取一个 Bean 时,通常情况下会得到同一个实例,这就是单例模式的应用。
代理模式(Proxy Pattern):
场景: Spring AOP(面向切面编程)中的代理模式。Spring AOP 通过代理模式创建代理对象,从而实现横切逻辑的注入。
举例: 当我们为一个类添加切面时,Spring AOP 会创建一个代理对象,将横切逻辑织入目标类的方法中。
观察者模式(Observer Pattern):
场景: Spring 中的事件监听机制,基于观察者模式实现。
举例: Spring 中的 ApplicationEvent 类和 ApplicationListener 接口,以及事件发布者 ApplicationEventPublisher 接口的实现,都是基于观察者模式的应用。
模板模式(Template Pattern):
场景: Spring 中的 JdbcTemplate 类使用了模板模式,将一些不变的步骤封装在模板方法中,而将可变的部分留给子类实现。
举例: JdbcTemplate 类中的 query、update 等方法提供了模板方法的实现,而这些方法的具体实现由不同的回调处理器(Callback)提供。
20、Spring中注入bean有几种方式?
- 构造器注入
- set方法注入
- 注解注入
21、SPI机制是什么,和Spring自动配置有啥关系
推荐参考(B站): 10分钟让你彻底明白Java SPI
简单描述:SPI机制是基于Java的,是一种服务发现机制,在META-INF/services/下找到对应配置并加载到java里。
Spring自动配置基于了Java的SPI机制,去classpath下的META-INF目录下找所有的spring.factories文件,然后将所有的spring.factories文件进行解析。
22、spring 自动配置 和自动装配区别
Spring自动配置和自动装配是Spring框架中的两个核心概念。
自动配置(Auto-Configuration): Spring Boot根据类路径上的jar依赖和配置自动设置应用程序的bean。例如,如果你的项目中包含了Spring Data JPA,那么Spring Boot会自动配置数据源、实体管理器等。
自动装配(Auto-Wiring): Spring应用程序中,Spring容器自动将依赖关系注入到组件中,而无需在代码中进行显式配置。这通常是通过使用@Autowired注解实现的。
23、spring bean 的线程池模型
在Spring框架中,你可以通过配置来设置bean的线程池模型。这通常是通过使用TaskExecutor接口以及它的实现类如ThreadPoolTaskExecutor来完成的。以下是一个配置线程池的例子:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); // 核心线程数
executor.setMaxPoolSize(20); // 最大线程数
executor.setQueueCapacity(500); // 队列大小
executor.setKeepAliveSeconds(60); // 线程空闲时间
executor.setThreadNamePrefix("MyThreadPool-"); // 线程名前缀
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略
executor.initialize();
return executor;
}
}
在这个配置中,我们定义了一个名为threadPoolTaskExecutor的线程池。你可以通过@Async注解来指定哪个方法应该在这个线程池中运行。例如:
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
@Async("threadPoolTaskExecutor")
public void executeAsyncTask() {
// 异步执行的任务
}
}
在这个例子中,executeAsyncTask方法会在名为threadPoolTaskExecutor的线程池中异步执行。
24、Component 注解跟 bean 注解它有什么区别?
@Component注解:放在类上,@Component通常作为父注解,用于派生更具体的注解,如@Service、@Repository和@Controller。
@Bean注解:放在方法上,需要和@Configuration注解一起使用。