Micronaut微服务编程式设置属性失败,求解决方案
Micronaut编程式配置属性注入失败问题解决
问题场景
在Micronaut微服务中,尝试通过编程方式设置属性(而非编写application.yml),但属性注入失败,自定义的PropertySourceLoader实现类中的load等方法完全没被调用。
现有代码
自定义配置源实现
import io.micronaut.context.env.ActiveEnvironment; import io.micronaut.context.env.PropertySource; import io.micronaut.context.env.PropertySourceLoader; import io.micronaut.core.io.ResourceLoader; import jakarta.inject.Singleton; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Optional; @Singleton public class CustomConfigSource implements PropertySourceLoader { @Override public Optional<PropertySource> load(String resourceName, ResourceLoader resourceLoader) { Map<String, Object> properties = new HashMap<>(); properties.put("this.is.property.name", "value"); return Optional.of(PropertySource.of("custom", properties)); } @Override public Optional<PropertySource> loadEnv(String resourceName, ResourceLoader resourceLoader, ActiveEnvironment activeEnvironment) { return Optional.empty(); } @Override public Map<String, Object> read(String name, InputStream input) throws IOException { return null; } }
属性注入代码
@Property(name = "this.is.property.name") private String myProperty;
错误信息
io.micronaut.http.server.RouteExecutor: Unexpected error occurred: Failed to inject value for field [myProperty]
问题根源
PropertySourceLoader是用于**解析外部资源文件(如yml、properties)**的扩展接口,它的实例不会被Micronaut作为Bean管理,所以你加的@Singleton注解无效,框架启动时根本不会扫描调用这个类。它的设计目标不是用来直接提供内存中的属性集合。
修复方案
方案1:实现PropertySourceLocator(推荐)
这是Micronaut官方推荐的编程式注入属性源的方式,框架启动时会自动调用所有PropertySourceLocator实现类来加载属性。
修改代码如下:
import io.micronaut.context.env.PropertySource; import io.micronaut.context.env.PropertySourceLocator; import io.micronaut.core.order.Ordered; import jakarta.inject.Singleton; import java.util.HashMap; import java.util.Map; @Singleton public class CustomConfigLocator implements PropertySourceLocator, Ordered { @Override public PropertySource locate(io.micronaut.context.env.Environment environment) { Map<String, Object> properties = new HashMap<>(); properties.put("this.is.property.name", "value"); // 设置属性源优先级,数值越小优先级越高,可覆盖低优先级的同key属性 return PropertySource.of("custom-properties", properties, Ordered.HIGHEST_PRECEDENCE); } @Override public int getOrder() { // 确保该属性源被优先加载 return Ordered.HIGHEST_PRECEDENCE; } }
方案2:启动时手动添加属性源
在应用启动类中直接向ApplicationContext添加自定义属性源:
import io.micronaut.context.ApplicationContext; import io.micronaut.context.env.PropertySource; import java.util.HashMap; import java.util.Map; public class Application { public static void main(String[] args) { Map<String, Object> customProps = new HashMap<>(); customProps.put("this.is.property.name", "value"); ApplicationContext context = ApplicationContext.builder() .propertySources(PropertySource.of("custom", customProps)) .start(); // 后续业务逻辑 } }
方案3:用@Factory提供配置Bean
如果只是需要注入单个或少量属性,也可以通过FactoryBean直接提供:
import jakarta.inject.Singleton; import io.micronaut.context.annotation.Factory; @Factory public class CustomConfigFactory { @Singleton public String myCustomProperty() { return "value"; } }
然后直接注入该Bean即可:
@Inject private String myCustomProperty;
验证
采用任意一种方案修改后,重新启动应用,@Property(name = "this.is.property.name")就能成功获取到值,自定义逻辑也会被正常执行。
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

