如何在@Configuration类中使@Autowired生效?解决空指针问题
问题分析与解决方案
首先,你的空指针异常根源在于Spring Bean的初始化顺序:
当Spring创建RabbitConfiguration这个Configuration Bean时,会先执行类的成员变量初始化逻辑——也就是private List<String> routingKeys = writeRoutingKeys();这行代码,而此时@Autowired private MyService myService;的注入操作还没完成,所以myService还是null,调用myService.getRoutingKeys()自然就抛出NPE了。
另外还有个小细节:你的MyService类是默认包访问权限(没有加public修饰符),虽然Spring能扫描到它,但从规范和兼容性角度,建议改成public,避免后续可能出现的类访问问题。
解决方案1:使用@PostConstruct延迟初始化逻辑
把writeRoutingKeys()的调用放到@PostConstruct注解的方法里,这个注解标注的方法会在Spring完成所有Autowired注入后执行:
package com.myapp.messaging; import com.myapp.resources.MyService; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.TopicExchange; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; import java.util.List; @Configuration public class RabbitConfiguration { private List<String> routingKeys; @Autowired private MyService myService; @PostConstruct public void initRoutingKeys() { boolean test = myService == null; System.out.println("is the service null? " + test); // 现在会输出false this.routingKeys = myService.getRoutingKeys(); } // RabbitMQ的Bean声明方法... }
解决方案2:改用构造注入
构造注入是Spring推荐的注入方式之一,它能保证在Bean实例化时就完成依赖注入,避免空指针问题:
package com.myapp.messaging; import com.myapp.resources.MyService; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.TopicExchange; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; @Configuration public class RabbitConfiguration { private List<String> routingKeys; private final MyService myService; // 构造注入,Spring会自动传入MyService的实例 public RabbitConfiguration(MyService myService) { this.myService = myService; this.routingKeys = writeRoutingKeys(); } private List<String> writeRoutingKeys() { boolean test = myService == null; System.out.println("is the service null? " + test); // 输出false return myService.getRoutingKeys(); } // RabbitMQ的Bean声明方法... }
解决方案3:在@Bean方法中直接使用依赖
如果你的routingKeys是用来配置RabbitMQ的Bean(比如Binding),可以直接在@Bean方法中注入MyService,这样Spring会确保依赖准备好:
package com.myapp.messaging; import com.myapp.resources.MyService; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.TopicExchange; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; import java.util.stream.Collectors; @Configuration public class RabbitConfiguration { @Bean public List<String> routingKeys(MyService myService) { return myService.getRoutingKeys(); } // 示例:在Binding Bean中使用routingKeys @Bean public List<Binding> bindings(Queue queue, TopicExchange exchange, List<String> routingKeys) { return routingKeys.stream() .map(key -> BindingBuilder.bind(queue).to(exchange).with(key)) .collect(Collectors.toList()); } // 其他RabbitMQ Bean声明... }
最后,记得把MyService改成public修饰符:
package com.myapp.resources; import org.springframework.stereotype.Service; import java.util.List; @Service public class MyService { // 添加public修饰符 public List<String> getRoutingKeys() { List<String> routingKeys; //Do stuff return routingKeys; } public String aMethod() { return "hello"; } }
内容的提问来源于stack exchange,提问作者Ivan Lamparelli
相关产品推荐
相关产品推荐

