1. 单例模式
单例模式是一种设计模式,确保一个类只有一个实例,并提供全局访问点。在 Spring 框架中,单例模式常用于管理共享资源,如数据库连接
(1) 使用单例模式改造数据库连接功能
在传统的应用中,每次需要数据库连接时可能会创建一个新的连接对象。这种做法会导致资源浪费和性能问题。通过单例模式,可以确保数据库连接对象在应用生命周期内只有一个实例,从而节省资源和提高效率
public class DatabaseConnection {
private static DatabaseConnection instance;
private Connection connection;
private DatabaseConnection() {
// 连接数据库的代码
this.connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/cvs_db?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8", "user", "password");
}
public static synchronized DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
public Connection getConnection() {
return connection;
}
}
在上面的代码中,DatabaseConnection
类是一个单例类。它通过私有构造函数限制实例化,并使用 getInstance()
方法来获取唯一的实例
(2) 懒汉模式和饿汉模式
-
懒汉模式:实例在第一次使用时创建
public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
-
饿汉模式:实例在类加载时创建
public class EagerSingleton { private static final EagerSingleton INSTANCE = new EagerSingleton(); private EagerSingleton() {} public static EagerSingleton getInstance() { return INSTANCE; } }
懒汉模式延迟加载实例,但需要考虑线程安全问题,而饿汉模式在类加载时即创建实例,避免了多线程同步问题。
- 静态内部类
原理
- 类加载机制:Java 保证一个类的构造方法在多线程环境下被正确地加载和初始化。静态内部类在使用时才加载,并且这种加载是线程安全的
- 懒加载:只有在调用
getInstance()
方法时,静态内部类才会加载,实例才会被创建 - 线程安全:由于静态内部类的加载机制,实例的创建是线程安全的
public class Singleton {
// 私有的构造方法,防止外部实例化
private Singleton() {}
// 静态内部类,持有单例的实例
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 提供外部访问单例实例的公共方法
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
静态内部类是一种实现单例模式的方式,结合了懒汉模式和饿汉模式的优点。它在需要的时候才创建实例,同时保证了线程安全
(3) SpringMVC 框架中的单例模式
Spring 框架默认使用单例模式来管理 bean,这意味着每个 bean 在 Spring 容器中只有一个实例。对于无状态的服务对象,这种模式非常有效。开发者可以使用 @Scope
注解改变 bean 的作用域,例如将其设置为 prototype
以每次请求创建一个新的实例
@Service
@Scope("singleton") // 默认值,单例模式
public class SysUserService {
// 业务逻辑
}
2. 异常处理
在开发过程中,异常处理是确保应用程序稳定性和用户体验的重要部分。Spring 提供了多种方式处理异常,包括局部异常处理和全局异常处理。
(1) 局部异常处理
局部异常处理用于在特定的控制器或方法中处理异常。可以使用 @ExceptionHandler
注解来定义处理特定异常的方法
@RestController
public class UserController {
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
if (id == null) {
throw new UserNotFoundException("用户不存在");
}
return userService.findById(id);
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
}
在上面的代码中,UserController
类中定义了一个 @ExceptionHandler
方法,用于捕获 UserNotFoundException
异常并返回自定义的错误消息和 HTTP 状态码
(2) 全局异常处理
全局异常处理用于在应用程序的任何地方处理异常,可以使用 @ControllerAdvice
注解和 @ExceptionHandler
注解结合使用。
@Controller
public class GlobalExceptionHandler {
@ExceptionHandler(value = {RuntimeException.class})
public String handleException(RuntimeException e, HttpServletRequest request) {
request.setAttribute("e", e);
return "error";
}
}
将@Controller注解替换成使用@ControllerAdvice
注解的类会自动应用于所有控制器,这样可以集中管理异常处理逻辑,减少代码的重复