Spring Boot配置文件属性加载失败及Environment注入null问题求助
Let's tackle your two main issues—Environment being null and loading config properties into a List<String>—with practical fixes tailored to your Spring Boot 2.2.2 setup.
1. Fixing the Environment Null Injection Problem
The root cause here is almost certainly that your DecisionInterceptor instance wasn't being managed by the Spring container when you tried to inject Environment. If you were manually creating the interceptor (e.g., new DecisionInterceptor()) and adding it to the interceptor chain, Spring can't auto-wire dependencies into unmanaged objects.
Solution:
Since you've already added @Component to DecisionInterceptor, make sure you're injecting it via Spring instead of instantiating it manually:
@Configuration public class WebServiceConfig extends WsConfigurerAdapter { @Autowired private DecisionInterceptor decisionInterceptor; @Override public void addInterceptors(List<EndpointInterceptor> interceptors) { interceptors.add(decisionInterceptor); } }
This way, Spring creates and manages the interceptor instance, allowing proper dependency injection of Environment (or your List<String> directly).
2. Properly Loading Config Properties into a List<String>
Your initial @Value approach works but has edge cases (like trailing spaces or empty config values) that can break your logic. Let's fix this with two robust options:
Option 1: Optimize the @Value Expression
Update your SpEL to handle whitespace and empty configurations automatically:
@Slf4j @Component public class DecisionInterceptor implements EndpointInterceptor { // Handles spaces, empty configs, and filters out blank values @Value("#{'${endpoints:}'.split(',')?.stream().map(String::trim).filter(s -> !s.isEmpty()).collect(java.util.stream.Collectors.toList())}") private List<String> endpoints; @Override public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception { if(endpoint instanceof MethodEndpoint) { MethodEndpoint methodEndpoint = (MethodEndpoint)endpoint; return endpoints.contains(methodEndpoint.getMethod().getName()); } return true; } // Rest of your interceptor methods... }
${endpoints:}sets a default empty string if the property isn't defined- The stream trims whitespace, filters out empty strings, and returns a clean list
Option 2: Use @ConfigurationProperties (Recommended for Spring Boot)
This is the more maintainable approach for binding config properties, especially as your configuration grows:
- Create a properties binding class:
@Configuration @PropertySource("classpath:endpoints.properties") @ConfigurationProperties(prefix = "") // Leave empty if your property has no prefix; use e.g., "app" if property was app.endpoints public class EndpointProperties { private List<String> endpoints; // Getters and setters public List<String> getEndpoints() { return endpoints; } public void setEndpoints(List<String> endpoints) { this.endpoints = endpoints; } }
Add the configuration processor dependency to your pom.xml (for auto-completion and validation):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
- Update your
endpoints.properties:
Spring Boot supports both comma-separated and array-style syntax:
# Option 1: Comma-separated endpoints=createUser,updateUser,deleteUser # Option 2: Array-style (useful for multi-line configs) # endpoints[0]=createUser # endpoints[1]=updateUser
- Inject the properties class into your interceptor:
Use constructor injection (Spring's recommended practice for better testability):
@Slf4j @Component public class DecisionInterceptor implements EndpointInterceptor { private final EndpointProperties endpointProperties; public DecisionInterceptor(EndpointProperties endpointProperties) { this.endpointProperties = endpointProperties; } @Override public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception { if(endpoint instanceof MethodEndpoint) { MethodEndpoint methodEndpoint = (MethodEndpoint)endpoint; List<String> endpoints = endpointProperties.getEndpoints(); // Guard against null to avoid NPE return endpoints != null && endpoints.contains(methodEndpoint.getMethod().getName()); } return true; } // Rest of your interceptor methods... }
Extra Notes
- You can remove the
PropertySourcesPlaceholderConfigurerbean fromAppConfig—Spring Boot auto-configures this for you, and manual registration can cause conflicts. - Ensure your
endpoints.propertiesis placed insrc/main/resourcesso Spring can locate it.
内容的提问来源于stack exchange,提问作者PAA

