Spring Boot中基于Meta注解的cursorBatchSize动态注入自定义注解问题
问题原因
原来的写法行不通,因为Spring的@Value注解不能直接用在自定义注解的属性上——注解属性的默认值是编译期确定的常量,@Value在这里不会被Spring解析,所以不管配置文件怎么配置,始终只会用默认的100。
解决方案
我们需要借助Spring的环境配置解析能力,结合Spring Data MongoDB的查询扩展机制,动态设置cursorBatchSize。具体步骤如下:
1. 重新定义自定义注解
去掉无效的@Value和@Meta元注解,改成带占位符的属性定义:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface DynamicMeta { // 用占位符支持配置文件注入,默认值100 String cursorBatchSize() default "${dynamic.cursor.batch.size:100}"; }
2. 实现查询后置处理器
编写一个QueryPostProcessor,在MongoDB查询执行前,解析@DynamicMeta注解的配置值,动态设置查询的Meta信息:
import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; import org.springframework.data.mongodb.core.query.Meta; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.repository.query.MongoQueryExecution; import org.springframework.data.mongodb.repository.query.MongoQueryMethod; import org.springframework.data.mongodb.repository.query.QueryPostProcessor; public class DynamicMetaQueryPostProcessor implements QueryPostProcessor<Query, MongoQueryExecution>, EnvironmentAware { private Environment environment; @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override public MongoQueryExecution postProcess(MongoQueryExecution execution, MongoQueryMethod queryMethod, Query query) { // 优先读取方法上的注解,没有则读取类上的 DynamicMeta dynamicMeta = queryMethod.getMethod().getAnnotation(DynamicMeta.class); if (dynamicMeta == null) { dynamicMeta = queryMethod.getRepositoryInterface().getAnnotation(DynamicMeta.class); } if (dynamicMeta != null) { // 解析占位符为实际数值 String batchSizeStr = environment.resolvePlaceholders(dynamicMeta.cursorBatchSize()); int batchSize = Integer.parseInt(batchSizeStr); // 给查询设置cursorBatchSize query.with(new Meta().cursorBatchSize(batchSize)); } return execution; } }
3. 注册处理器到Spring容器
在配置类中把上面的处理器注册成Bean:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MongoConfig { @Bean public DynamicMetaQueryPostProcessor dynamicMetaQueryPostProcessor() { return new DynamicMetaQueryPostProcessor(); } }
4. 使用自定义注解
直接在Repository接口或方法上添加@DynamicMeta即可:
import org.springframework.data.mongodb.repository.MongoRepository; import java.util.List; // 类级别的配置,所有方法默认使用这个配置 @DynamicMeta public interface UserRepository extends MongoRepository<User, String> { // 方法级别的配置,会覆盖类级别 @DynamicMeta(cursorBatchSize = "${dynamic.cursor.batch.size:200}") List<User> findByAgeGreaterThan(int age); }
这样配置后,执行查询时Spring会自动读取application.properties中的dynamic.cursor.batch.size值,动态设置MongoDB查询的游标批次大小。
内容的提问来源于stack exchange,提问作者Shankar Shastri
相关产品推荐
相关产品推荐

