资源预加载
- 原理:在应用启动阶段提前加载一些必要的资源,避免在运行时才加载导致的延迟。
- 实现方式:
- 使用
@PostConstruct
注解:在自定义 Starter 的某个配置类中,定义一个方法并使用 @PostConstruct
注解。例如:
import org.springframework.stereotype.Component;
@Component
public class ResourcePreloader {
@PostConstruct
public void preloadResources() {
// 这里进行资源预加载的逻辑,比如加载数据库连接池的配置等
}
}
- 使用
ApplicationListener<ContextRefreshedEvent>
:创建一个监听器类实现 ApplicationListener<ContextRefreshedEvent>
接口,在 onApplicationEvent
方法中进行资源预加载。
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class MyContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 资源预加载逻辑
}
}
按需加载
- 原理:只有在实际需要使用某个配置或资源时才进行加载,避免不必要的初始化开销。
- 实现方式:
- 懒加载配置类:在配置类上使用
@Lazy
注解。例如:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Configuration
@Lazy
public class LazyConfig {
@Bean
public SomeService someService() {
return new SomeService();
}
}
- 使用
ObjectProvider
:在需要使用某个 bean 的地方,通过 ObjectProvider
来获取,只有在真正调用 getIfAvailable
等方法获取 bean 时才会进行初始化。例如:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ObjectProvider;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final ObjectProvider<SomeService> someServiceProvider;
@Autowired
public MyService(ObjectProvider<SomeService> someServiceProvider) {
this.someServiceProvider = someServiceProvider;
}
public void doSomething() {
someServiceProvider.getIfAvailable(someService -> {
// 使用 someService 进行业务处理
return null;
});
}
}
- 条件化配置(
@Conditional
):通过 @Conditional
注解,根据一定的条件来决定是否加载某个配置类或 bean。例如,只有在特定环境变量存在时才加载某个配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConditionalConfig {
@Bean
@Conditional(MyCondition.class)
public SomeService someService() {
return new SomeService();
}
}
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 判断环境变量等条件
String someEnvVar = context.getEnvironment().getProperty("some.env.var");
return "specificValue".equals(someEnvVar);
}
}
减少不必要配置加载
- 原理:移除那些确实不需要的配置,减少 Spring Boot 启动时的加载负担。
- 实现方式:
- 分析项目需求:仔细梳理项目功能,确认哪些配置是真正必需的。例如,如果项目不使用消息队列,那么相关的消息队列配置(如 RabbitMQ 等)就可以移除。
- 排除自动配置:使用
@SpringBootApplication(exclude = {SomeAutoConfiguration.class})
来排除不需要的自动配置类。例如,如果不想加载 Spring Data JPA 的自动配置,可以这样写:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jpa.HibernateJpaAutoConfiguration;
@SpringBootApplication(exclude = {HibernateJpaAutoConfiguration.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
优化配置文件读取
- 原理:提高配置文件的读取效率,避免复杂的解析过程。
- 实现方式:
- 使用属性占位符优化:在配置文件中合理使用属性占位符,减少重复配置。例如,在
application.properties
中:
app.base-url = http://example.com
app.api-url = ${app.base-url}/api
- 配置文件结构优化:保持配置文件结构清晰,避免过多层级嵌套。例如,将相关配置放在同一层级下,而不是嵌套过深。比如对于数据库配置:
# 良好的结构
spring.datasource.url = jdbc:mysql://localhost:3306/mydb
spring.datasource.username = root
spring.datasource.password = password
# 避免这样过度嵌套(虽然 Spring Boot 支持)
spring.datasource.connection.url = jdbc:mysql://localhost:3306/mydb
spring.datasource.connection.username = root
spring.datasource.connection.password = password