spring知识点
Spring
线程安全
-
单例
是,可以用Scope注解来改变为prototype。
-
线程安全
bean对象一般都是无状态类(eg: services、DAO),不可被修改;所以一定程度上不存在线程安全问题,如果提供了可变成员变量,一定要注意线程安全问题。
AOP
面向切面编程,抽离公共行为与逻辑,与业务无关,底层是动态代理。(接口:cglib,抽象类:jdk)
-
认证鉴权
-
系统日志
-
预加载配置数据进缓存
-
spring内置的事务处理
在方法前后开启拦截,方法前开启事务,方法中处理事务,方法后提交事务或者异常中回滚事务。
事务失效
-
异常被吞
原因:异常被吞掉,而不是向上抛出,导致AOP拿不到业务异常,从而不能回滚。解决:
throw new RuntimeExecpiton(e) -
抛出检查异常
原因:默认Spring事务只回滚非检查类异常。解决:
@Transactional(roolbackFor = Exception.class) -
方法为非public
原因:spring只为public修饰的方法添加事务、创建代理等功能。
解决:方法修饰改为public
循环依赖
循环引用指的是两个或多个Bean之间相互依赖,形成了一个闭环的情况。例如,Bean A依赖于Bean B,而Bean B又依赖于Bean A。如果没有循环引用的自检机制,程序在创建Bean时可能会进入无限递归的循环,并最终导致栈溢出错误。
- 自检
是的,Spring框架在创建Bean时会进行循环引用的自检测。当Spring容器在初始化Bean时发现存在循环依赖关系时,它会抛出BeanCurrentlyInCreationException
异常,以避免无限递归的循环引用。
SpringMVC
前后端一体化
-
前段发起请求进入DispatcherServlet
-
根据URI询问HandlerMapping
-
返回HandlerExecutionChain(拦截器链),包含以下对象:
- Handler对象:指定要执行的处理器方法,即Controller类中的方法。
- Interceptor对象列表:包含一系列处理器拦截器,用于在请求处理前、处理过程中和处理后执行一些特定的逻辑。
-
DispatherServlet调用HandlerAdapter完成请求消息的解析以及返回数据的封装。
DispatcherServlet根据Handler对象的类型和其他条件选择合适的HandlerAdapter。Spring提供了多个默认的HandlerAdapter实现,如RequestMappingHandlerAdapter、HttpRequestHandlerAdapter等RequestMappingHandlerAdapter:当你的处理器方法使用注解方式进行映射,即使用@RequestMapping等注解来标识请求路径、请求方法等信息时,可以选择使用RequestMappingHandlerAdapter。这个适配器能够处理被注解标记的处理器方法,并根据请求的路径和HTTP方法来调用相应的处理器方法。
HttpRequestHandlerAdapter:当你的处理器是实现了HttpRequestHandler接口的类时,可以选择使用HttpRequestHandlerAdapter。HttpRequestHandler是一个简单的接口,只有一个handleRequest方法,它负责处理传入的请求并生成响应。
- 执行拦截器的preHandle方法 如请求数据的二次封装、权限验证、日志记录等。
- 执行处理器方法 拿到请求对象进行业务处理。
- 执行拦截器的postHandle方法 修改模型数据、返回数据修改、日志请求链数据入库等。
- 执行拦截器的完成处理(afterCompletion)进行资源释放等。
-
返回 ModelAndView 给DispatcherServlet
- 视图名称:指定要渲染的视图的名称或标识符。视图名称可以是JSP页面、Thymeleaf模板或其他类型的视图
- 模型数据:包含需要在视图中展示的数据。模型数据可以是Java对象、集合、Map等,用于在视图中动态地显示数据。
- 其他属性:可能包括一些附加的属性或配置信息,用于定制视图的渲染过程。
-
会根据其中的视图名称、模型数据等信息,调用相应的视图解析器(ViewResolver) , 进行解析和渲染操作
前后端分离
与一体化前四步一样, 返回其他类型的对象,如ResponseBody、DeferredResult等,用于直接返回数据或进行异步处理。
Tips:Springmvc默认用 MappingJackson2HttpMessageConverter 作为消息转换器来处理@ResponseBody注解标记的方法返回值,并将其转换为JSON格式。这是因为JSON在Web应用开发中被广泛使用,而且更适合RESTful风格的API。
SpringBoot
自动装载
核心原理:SPI,通过AutoConfigruationImportSelector.classs找到Spring.factories ,Spring Boot会根据条件注解(如@ConditionalOnClass
、@ConditionalOnBean
、@ConditionalOnMissingBean
等)对自动装载进行条件判断(是否已经在pom中引入依赖包),只有满足特定条件的自动装载才会生效。
JDKSPI:根据 资源路径下的META-INF/services
目录下的以完整全限定名接口名命名的配置文件加载接口以及对应的实现类。
常用注解
-
@Autowried
根据类型type装载,经常用于接口只有一个实现类的场景。如果有多个实现类和@Qualifier结合使用 -
@Requried
根据name加载
mybatis
执行流程
- 读取mybatis-config.xml文件,构建运行环境和加载映射文件。
- 构建会话工厂SQLSessionFactory以及SqlSession对象(Spring容器中的单例,复用数据库连接资源)。
- SqlSession构建Execute对象执行sql语句以及缓存查询结果。
- Execute的方法入参有一核心MapStatement对象,构建了映射关系(请求参数映射、maper文件对象映射、返回结果映射)
延迟加载
适用于关联对象的查询延迟加载,支持局部和全局。
原理:
- 使用CGLIB创建代理对象。
- 当调用目标 getter方法 时,调用invoke方法,发现结果为null,执行sql查询。
- 获取数据后,调用set方法设置属性值,再查寻目标方法就有结果了。
缓存
-
一级缓存
session级别,共享session。存在PerpetualCache的hashmap中。 -
二级缓存
namespace和map级别,也是存于PerpetualCache的hashmap中 -
缓存时效
当某个作用域中有新增、删除、更改时,select中的缓存会被清空。
知识点
检查类异常
在Java中,有两种类型的异常:受检查异常(Checked Exceptions)和非受检查异常(Unchecked Exceptions)。受检查异常是指必须在方法声明中显式处理或声明抛出的异常,而非受检查异常则不需要。
以下是一些常见的受检查异常:
- IOException:输入输出操作发生错误时抛出的异常。
- SQLException:在数据库访问过程中发生错误时抛出的异常。
- FileNotFoundException:尝试访问不存在的文件时抛出的异常。
- ClassNotFoundException:尝试加载不存在的类时抛出的异常。
- ParseException:解析字符串为特定格式时发生错误时抛出的异常。
- InterruptedException:线程在等待时被中断时抛出的异常。
- NoSuchMethodException:尝试调用不存在的方法时抛出的异常。
除了受检查异常之外,还有一些常见的非受检查异常,也称为运行时异常(RuntimeExceptions):
- NullPointerException:当引用为空时尝试访问它时抛出的异常。
- ArrayIndexOutOfBoundsException:尝试访问数组中不存在的索引时抛出的异常。
- IllegalArgumentException:传递给方法的参数无效时抛出的异常。
- IllegalStateException:对象状态不正确时抛出的异常。
- ArithmeticException:算术运算发生错误时抛出的异常。
这些只是一些常见的受检查异常和非受检查异常示例,实际上Java中有更多的异常类可以用于处理特定的错误情况。在编写代码时,根据具体的操作和条件,选择适当的异常类型来捕获和处理异常是很重要的。
策略模式
在Spring框架中,可以通过使用@Service
或@Component
注解来定义不同的策略实现,并通过@Autowired
注解将它们自动注入到一个Map中,以实现策略模式。下面是一个使用Spring自动注入Map Bean来实现策略模式的示例:
首先,定义一个策略接口:
public interface Strategy { void execute(); }
然后,创建不同的策略实现,并使用@Service
注解为每个策略指定一个唯一的名称:
@Service("strategyA") public class ConcreteStrategyA implements Strategy { @Override public void execute() { // 实现策略A的逻辑 } } @Service("strategyB") public class ConcreteStrategyB implements Strategy { @Override public void execute() { // 实现策略B的逻辑 } } // 可以继续添加更多策略实现...
接下来,创建一个策略工厂,它将使用Spring的自动注入功能来注入所有策略实现到一个Map中:
@Component public class StrategyFactory { private final Map<String, Strategy> strategies; @Autowired public StrategyFactory(Map<String, Strategy> strategies) { this.strategies = strategies; } public Strategy getStrategy(String strategyName) { Strategy strategy = strategies.get(strategyName); if (strategy == null) { throw new IllegalArgumentException("No strategy found for name: " + strategyName); } return strategy; } }
最后,在需要使用策略的地方,可以通过策略工厂来获取并执行相应的策略:
@RestController public class StrategyController { private final StrategyFactory strategyFactory; @Autowired public StrategyController(StrategyFactory strategyFactory) { this.strategyFactory = strategyFactory; } @PostMapping("/executeStrategy") public ResponseEntity<String> executeStrategy(@RequestParam String strategyName) { Strategy strategy = strategyFactory.getStrategy(strategyName); strategy.execute(); return ResponseEntity.ok("Strategy " + strategyName + " executed successfully"); } }
在这个例子中,我们定义了一个策略接口和两个具体的策略实现。通过@Service
注解和指定的名称,Spring会自动将这些策略实现注入到StrategyFactory
中的Map里。当控制器接收到一个请求时,它会使用策略工厂来查找并执行相应的策略。这种方式使得策略模式的实现更加灵活和可扩展。
异常捕获
在Spring Boot中,异常处理是确保应用程序稳定性和提供良好用户体验的关键部分。以下是Spring Boot异常捕获的最佳实践的实现代码示例:
- 创建自定义异常类:首先,定义一个自定义异常类,例如
ProductNotFoundException
,用于处理特定的业务逻辑异常。
public class ProductNotFoundException extends RuntimeException { public ProductNotFoundException(Long productId) { super("产品未找到,ID: " + productId); } }
- 创建服务层:在服务层中,当特定条件不满足时(例如,找不到产品),抛出自定义异常。
import org.springframework.stereotype.Service; @Service public class ProductService { public Product getProductById(Long productId) { // 模拟从数据库获取产品信息 Product product = getProductFromDatabase(productId); if (product == null) { throw new ProductNotFoundException(productId); } return product; } private Product getProductFromDatabase(Long productId) { // 实现数据库逻辑 return null; // 假设找不到产品,返回null } }
- 全局异常处理:使用
@ControllerAdvice
注解创建一个全局异常处理类,用于捕获和处理特定类型的异常。
@ControllerAdvice public class GlobalExceptionHandler { // 已存在的ProductNotFoundException处理方法 @ExceptionHandler(ProductNotFoundException.class) public ResponseEntity<ErrorResponse> handleProductNotFoundException(ProductNotFoundException ex) { ErrorResponse errorResponse = new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage()); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); } // 处理所有未被上面处理的异常 @ExceptionHandler(Exception.class) public ResponseEntity<ErrorResponse> handleAllUncaughtException(Exception ex) { ErrorResponse errorResponse = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器内部错误,请联系管理员。"); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); } // 可以添加更多的异常处理方法来处理特定类型的异常 // 例如,处理无效请求参数异常 @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) { ErrorResponse errorResponse = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), "请求参数无效: " + ex.getMessage()); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse); } }
- 定义错误响应类:创建一个错误响应类
ErrorResponse
,用于构造异常处理方法返回的错误信息。
public class ErrorResponse { private int statusCode; private String message; public ErrorResponse(int statusCode, String message) { this.statusCode = statusCode; this.message = message; } // Getter和Setter方法 public int getStatusCode() { return statusCode; } public void setStatusCode(int statusCode) { this.statusCode = statusCode; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
- 控制器:创建一个控制器,用于处理客户端请求,并使用
ProductService
获取产品信息。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/products") public class ProductController { @Autowired private ProductService productService; @GetMapping("/{productId}") public ResponseEntity<Product> getProduct(@PathVariable Long productId) { Product product = productService.getProductById(productId); return ResponseEntity.ok(product); } }
通过上述步骤,我们实现了一个基本的Spring Boot异常处理流程,包括自定义异常的抛出、全局异常的捕获与处理,以及错误响应的构造和返回。这样可以确保应用程序在遇到异常时能够返回清晰、一致的错误信息给客户端,提高用户体验。
本文作者:唐钰逍遥
本文链接:https://www.cnblogs.com/tyxy/p/17808324.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步