SmartInitializingSingleton
在继续深入探讨
SmartInitializingSingleton
接口之前,让我们先了解一下Spring Framework
的基本概念和背景。Spring Framework 是一个开源的 JavaEE(Java Enterprise Edition)全栈(full-stack)轻量级应用程序框架,用于开发企业级应用程序。它提供了广泛的基础设施支持和丰富的特性,以简化企业级应用程序的开发。
1. Spring Framework 概述
Spring Framework 的核心特性包括:
1.1 控制反转(Inversion of Control,IoC)
Spring 使用控制反转(IoC)原则来管理对象之间的依赖关系。在传统的 Java 开发中,对象的创建和依赖关系通常由程序员自己管理,而在 Spring 中,容器负责创建对象并将它们装配起来。这种方式将对象之间的依赖关系从代码中解耦,提高了代码的灵活性和可维护性。
1.2 依赖注入(Dependency Injection,DI)
依赖注入是控制反转的一种实现方式,它通过将对象的依赖关系注入到对象本身,来实现对象之间的解耦。Spring 使用依赖注入来管理对象之间的依赖关系,通过配置文件或者注解来描述对象之间的关系,然后由 Spring 容器负责将依赖关系注入到对象中。
1.3 切面编程(Aspect-Oriented Programming,AOP)
切面编程是一种用于将横切关注点(cross-cutting concerns)从应用程序的核心逻辑中分离出来的编程范式。在 Spring 中,通过 AOP 可以实现诸如日志记录、性能监控、事务管理等与业务逻辑无关的功能,从而提高代码的模块化和可重用性。
1.4 面向接口编程(Interface-Based Programming)
Spring 鼓励使用面向接口编程的方式来开发应用程序,这样可以提高代码的灵活性和可扩展性。Spring 的许多特性都是基于接口实现的,如依赖注入、AOP 等,这使得开发者可以很容易地实现自己的定制功能。
1.5 配置简化
Spring 提供了多种配置方式,包括基于 XML 的配置、基于注解的配置和基于 Java 的配置,使得开发者可以根据自己的习惯和项目的需求选择合适的配置方式,并且可以灵活地切换配置方式而不影响应用程序的正常运行。
1.6 模块化设计
Spring Framework 被设计为一组相互独立、松耦合的模块,每个模块都提供特定的功能,如核心容器、数据访问/集成、Web 开发、AOP 支持等。开发者可以根据自己的需求选择需要的模块,而不必引入整个框架。
2. SmartInitializingSingleton 接口介绍
现在让我们转向本文的重点:SmartInitializingSingleton
接口。在 Spring Framework
中,SmartInitializingSingleton
是一个特殊的接口,用于在 Spring 容器中所有单例 Bean 初始化完成后执行一些自定义的初始化逻辑。它允许开发者在所有单例 Bean 都已经准备就绪后执行一些特定的操作,这对于需要在应用程序启动时进行一些额外的初始化工作的场景非常有用。
2.1 SmartInitializingSingleton 接口定义
javaCopy codepublic interface SmartInitializingSingleton {
void afterSingletonsInstantiated();
}
SmartInitializingSingleton 接口非常简单,只有一个方法:afterSingletonsInstantiated()。在 Spring 容器中所有的单例 Bean 都初始化完成之后,Spring 容器会回调实现了 SmartInitializingSingleton 接口的类的 afterSingletonsInstantiated() 方法,从而触发相应的初始化逻辑。
2.2 使用示例
让我们通过一个简单的示例来说明如何使用 SmartInitializingSingleton 接口。假设我们有一个需要在所有单例 Bean 初始化完成后执行初始化逻辑的场景,我们可以定义一个实现了 SmartInitializingSingleton 接口的类,然后在其中实现 afterSingletonsInstantiated() 方法来执行相应的初始化逻辑。
javaCopy code@Component
public class MyInitializer implements SmartInitializingSingleton {
private static final Logger logger = LoggerFactory.getLogger(MyInitializer.class);
@Override
public void afterSingletonsInstantiated() {
// 执行初始化逻辑
logger.info("All singleton beans have been instantiated.");
// 可以在这里执行一些初始化操作,如加载配置文件、初始化缓存等
}
}
在上面的示例中,我们定义了一个名为 MyInitializer
的类,它实现了SmartInitializingSingleton
接口,并重写了 afterSingletonsInstantiated()
方法。在这个方法中,我们可以执行任何需要在所有单例 Bean 初始化完成后执行的初始化逻辑。
3.案例
3.1 初始化缓存信息
在项目开发中,用户经常会浏览各种商品,如服装、家居用品、电子设备等。为了提高用户体验和系统性能,平台决定引入缓存机制来存储商品信息,以减少对数据库的频繁访问。在系统启动时,需要初始化商品信息的缓存(从数据库中进行查询),以便在用户请求时快速响应。为了实现这一目标,我们将使用 Spring 框架的 SmartInitializingSingleton 接口来在所有单例 Bean 初始化完成后执行初始化缓存的操作。
3.1.2 创建商品实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
/**
* 商品id唯一
*/
private String goodId;
/**
* 商品名称
*/
private String goodName;
/**
* 商品价格
*/
private BigDecimal price;
public String toString(Product product){
StringBuffer sb = new StringBuffer();
sb.append("商品id:").append(product.getGoodId()).append("商品名称:").append(product.getGoodName()).append("商品价格:").append(product.getPrice());
return sb.toString();
}
}
3.1.3 编写商品缓存类
/**
*
* 商品缓存类型
* @author 13723
* @version 1.0
* 2024/2/24 12:49
*/
@Component
public class ProductCache implements SmartInitializingSingleton {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
/**
* 商品缓存Map
*/
private static final Map<String,Product> goodMap = new HashMap<>();
/**
* 添加商品到缓存
* @param product
*/
public void addGood(Product product){
// 添加商品到缓存
goodMap.put(product.getGoodId(),product);
}
/**
* 根据商品id获取商品
*/
public Product getGoods(String goodId){
Product product = goodMap.get(goodId);
if (product == null){
logger.error("未查询到商品!");
}
return product;
}
public void initializingGoods(){
// 初始化商品信息
Product product1 = new Product("1", "手机", new BigDecimal("111.23"));
Product product2 = new Product("2", "笔记本", new BigDecimal("1121.23"));
Product product3 = new Product("3", "相机", new BigDecimal("3331.23"));
Product product4 = new Product("4", "游戏机", new BigDecimal("12111.23"));
addGood(product1);
addGood(product2);
addGood(product3);
addGood(product4);
logger.error("=========== 初始化商品信息完成 ===========");
}
/**
* 在项目启动时,所有的单例bean都实例化完成后,会调用该方法
*/
@Override
public void afterSingletonsInstantiated() {
// 初始化商品信息
initializingGoods();
}
}
3.1.4 编写测试类
@Test
@DisplayName("测试SmartInitializingSingleton Bean加载")
public void testSmartInitializingSingleton(){
// 测试SmartInitializingSingleton Bean加载
logger.error("商品信息未:{}",productCache.getGoods("1"));
logger.error("商品信息未:{}",productCache.getGoods("2"));
logger.error("商品信息未:{}",productCache.getGoods("3"));
}
4. SmartInitializingSingleton 的使用场景
SmartInitializingSingleton
接口提供了一种灵活的机制来处理在 Spring 容器启动时需要执行的初始化逻辑。它适用于许多场景,包括但不限于:
4.1 加载配置信息
在应用程序启动时,可能需要加载一些配置信息,如数据库连接信息、系统参数等。SmartInitializingSingleton
接口可以用来执行这些初始化操作,确保在所有单例 Bean 初始化完成之后再加载配置信息。
4.2 初始化缓存
在应用程序启动时,可以使用 SmartInitializingSingleton
接口来初始化缓存,以提高系统的性能和响应速度。通过在所有单例 Bean 初始化完成后执行初始化缓存的操作,可以确保缓存数据已经准备就绪,从而避免了在系统运行时动态加载数据造成的性能损耗。
4.3. 执行定时任务
在某些情况下,可能需要在应用程序启动时执行一些定时任务,如数据同步、数据清理等。SmartInitializingSingleton
接口可以用来执行这些定时任务,以确保它们在所有单例 Bean 初始化完成之后立即执行。
总结
在本文中,我们介绍了 Spring Framework 的核心特性和背景,并深入探讨了 SmartInitializingSingleton
接口。通过实现 SmartInitializingSingleton
接口,开发者可以在 Spring 容器中所有单例 Bean 初始化完成后执行一些自定义的初始化逻辑,从而提高应用程序的灵活性和可维护性。我们还介绍了 SmartInitializingSingleton
接口的使用示例和常见的使用场景,希望能够帮助开发者更好地理解和应用这一特性。
总的来说,SmartInitializingSingleton
接口为 Spring 应用程序提供了一个强大而灵活的初始化机制,可以满足各种复杂应用程序的初始化需求,是 Spring Framework
中的一个重要组成部分。开发者可以根据自己的实际需求,合理地使用 SmartInitializingSingleton
接口来优化应用程序的初始化过程,提高系统的性能和可靠性。