使用@Autowired时抽象类子类对象为null的问题排查
问题根源与解决方案
嘿,这个问题我太熟了!你遇到的type1Processor等子类对象为null的核心原因是:你在main方法里手动new了一个ReactiveSocketServerApplication实例,这个对象完全不受Spring容器的管理。
Spring的依赖注入只对它自己创建并纳入容器的bean生效——你看到ReceivedDataService和Processor子类的构造函数被调用,是因为Spring已经悄悄创建了这些类的bean实例,但这些实例和你手动new的那个ReactiveSocketServerApplication半毛钱关系都没有,Spring根本不会去处理你手动new出来的对象上的@Autowired注解,所以那些字段自然都是null。
解决办法(推荐第一种)
方案1:让启动类实现CommandLineRunner接口
这是Spring Boot启动后执行初始化逻辑的标准做法,Spring会在容器完全初始化完成后自动调用run方法,此时所有注入的bean都已经准备就绪:
@SpringBootApplication public class ReactiveSocketServerApplication implements CommandLineRunner { private AppServer appServer; @Autowired Type1Processor type1Processor; @Autowired Type2Processor type2Processor; @Autowired Type3Processor type3Processor; public static void main(String[] args) { SpringApplication.run(ReactiveSocketServerApplication.class, args); } @Override public void run(String... args) throws Exception { // 在这里执行你的启动逻辑 startServer(); } private void startServer(){ appServer = AppServer.getInstance(); Map<Integer, Processor> processorMap = new HashMap<>(); processorMap.put(7001, type1Processor); processorMap.put(7002, type2Processor); processorMap.put(7003, type3Processor); appServer.initialize(processorMap); new ClientHandler(7001, 1000); new ClientHandler(7002, 5000); } }
方案2:从Spring上下文手动获取bean
如果你非要在main方法里处理,可以通过SpringApplication.run的返回值拿到ApplicationContext,再从中取出需要的bean:
@SpringBootApplication public class ReactiveSocketServerApplication { private AppServer appServer; public static void main(String[] args) { // 获取Spring上下文 ApplicationContext context = SpringApplication.run(ReactiveSocketServerApplication.class, args); // 从上下文取出需要的bean Type1Processor type1Processor = context.getBean(Type1Processor.class); Type2Processor type2Processor = context.getBean(Type2Processor.class); Type3Processor type3Processor = context.getBean(Type3Processor.class); ReactiveSocketServerApplication app = new ReactiveSocketServerApplication(); app.startServer(type1Processor, type2Processor, type3Processor); } private void startServer(Type1Processor type1Processor, Type2Processor type2Processor, Type3Processor type3Processor){ appServer = AppServer.getInstance(); Map<Integer, Processor> processorMap = new HashMap<>(); processorMap.put(7001, type1Processor); processorMap.put(7002, type2Processor); processorMap.put(7003, type3Processor); appServer.initialize(processorMap); new ClientHandler(7001, 1000); new ClientHandler(7002, 5000); } }
小补充:抽象类的@Component注解
你的抽象类Processor没有加@Component,不过因为子类都标注了@Component,Spring会正常扫描并创建子类的bean,这部分没问题。如果后续需要让抽象类作为组件基类被Spring识别,也可以给它加上@Component(不是必须的)。
内容的提问来源于stack exchange,提问作者masoud vali
相关产品推荐
相关产品推荐

