Spring Boot进阶:原理、实战与面试题分析
上QQ阅读APP看书,第一时间看更新

2.4.4 不同配置的性能分析

在本小节中,我们将讨论不同类型的Bean配置如何影响应用程序性能,并且我们还将讨论Bean配置的一些最佳实践。

首先要讨论的是前面介绍的@ComponentScan注解。因为该注解会扫描basePackages指定的包中的所有组件,所以如果所指定包中的组件并不需要在应用程序启动时就全部加载到容器中,那么对包路径进行精细化设计是一个实践技巧。例如,我们可以通过设置一个列表来细化具体的包结构路径,如代码清单2-32所示。

代码清单2-32 在@ComponentScan注解中指定的包结构路径示例代码

@Configuration
@ComponentScan(basePackages="com.spring.bestpractice.service","com.spring.bestpractice.controller")
public class AppConfig { }

然后要讨论的是单例模式和原型模式对性能的影响。在Spring中,当把Bean范围设置为prototype时,每次请求Bean时,Spring IoC容器都会创建一个新的对象实例。所以,使用原型模式在创建过程中会对性能产生影响,对那些初始化过程需要消耗巨大资源的对象而言尤其如此,这些对象常见的有网络连接对象、数据库连接对象等。因此,对这些对象,应该完全避免使用原型模式。或者,我们应该在使用前仔细设计并对性能进行充分测试。

最后一个值得讨论的性能分析点在于Spring IoC容器的延迟加载(Lazy Loading)和预加载(Preloading)机制。通过@Autowired注入的Bean都是在Spring IoC容器启动时被创建和初始化的,这个过程被称为预加载。但有时候,我们希望能够延迟Bean的加载时机,这时候就可以使用@Lazy注解,使用方法如代码清单2-33所示。

代码清单2-33 @Lazy注解示例代码

@Component
@Lazy
public class HealthRecordServiceImpl implements HealthRecordService { }

添加了@Lazy注解的效果是只有在使用到这个Bean时它才会去初始化,而不是在Spring IoC容器启动时直接初始化,这样就可以节省容器资源。

延迟加载确保在请求时动态加载Bean,预加载确保在使用Bean之前加载Bean。Spring IoC容器默认使用预加载。然而,在容器启动时就加载所有类(即使它们没有被使用)并不是一个明智的决定,因为有些Bean实例会非常消耗资源。我们应该根据实际情况选择具体的加载方法。如果需要尽快地加载应用程序,那么就采用延迟加载;如果需要应用程序尽快地运行并更快地为请求提供服务,那么就执行预加载。