【问题标题】:@Autowire field has Null Pointer Exception ['new' keyword not used]@Autowire 字段有空指针异常 ['new' 关键字未使用]
【发布时间】:2017-07-08 08:01:28
【问题描述】:

我已经尝试过Why is my Spring @Autowired field null? 中提到的解决方案,但问题仍然存在。我尝试使用@Configurable @Service 注释类DevicePojo(下面的代码)。

这是我的豆子 DistributionConfig.java

@Component
@Configuration
public class DistributionConfig {

    @Qualifier("exponentialDistribution")
    @Bean
    @Scope("prototype")
    public DistributionService exponentialDistribution() {
        return new ExponentiallyDistribute();
    }

    @Qualifier("normalDistribution")
    @Bean
    @Scope("prototype")
    public DistributionService normalDistribution() {
        return new NormallyDistribute();
    }

    @Qualifier("uniformDistribution")
    @Bean
    @Scope("prototype")
    public DistributionService uniformDistribution() {
        return new UniformlyDistribute();
    }
}

JsonFileConfig.java

@Configuration
public class JsonFileConfig {

    private static ObjectMapper mapper=new ObjectMapper();

    @Qualifier("devicesPojo")
    @Bean
    public DevicesPojo[] devicesPojo() throws Exception {
        DevicesPojo[] devicePojo=mapper.readValue(new File(getClass().getClassLoader().getResource("Topo/esnet-devices.json").getFile()),DevicesPojo[].class);
        return devicePojo;
    }


    @Qualifier("linksPojo")
    @Bean
    public LinksPojo[] linksPojo() throws Exception {
        LinksPojo[] linksPojo=mapper.readValue(new File(getClass().getClassLoader().getResource("Topo/esnet-adjcies.json").getFile()),LinksPojo[].class);
        return linksPojo;
    }
}

这是我的 DevicePojo,我得到空指针异常。

@JsonDeserialize(using = DeviceDeserializer.class)
@Component
public class DevicesPojo {

    private String device;
    private List<String> ports;
    private List<Integer> bandwidth;

    @Autowired
    @Qualifier("uniformDistribution")
    private DistributionService uniformDistribution; // Here uniformDistribution is null

    public DevicesPojo(String device, List<String> port, List<Integer> bandwidth) {
        this.device = device;
        this.ports= port;
        this.bandwidth=bandwidth;
        this.uniformDistribution.createUniformDistribution(1000,0,ports.size());
    }

    public String getDevice(){
        return device;
    }

    public String getRandomPortForDevice()
    {
       return ports.get((int)uniformDistribution.getSample());
    }

    public List<String> getAllPorts(){
       return ports;
    }

    public int getBandwidthForPort(String port){    
       return bandwidth.get(ports.indexOf(port));
    }
}

但是,如果我将 private DistributionService uniformDistribution; 替换为 private DistributionService uniformDistribution=new UniformDistribution(),则代码可以正常工作。

【问题讨论】:

  • 为什么你认为“映射器”应该“尊重”弹簧注释?当您使用mapper.readValue 时,会生成一个new DevicesPojo。一种解决方案是让映射器做他的事情,然后在结果上“设置” DistributionService(DistributionService 你得到一些@Autowired)
  • 只要我在 DevicePojo 中添加了@Autowired,它就可以正常工作。怎么了?
  • 你能详细说明一下吗?某种伪代码会有所帮助。

标签: java spring exception javabeans


【解决方案1】:

这里有各种各样的问题。
1. 您使用 JSON 反序列化器创建您的 DevicesPojo 对象。 Spring 没有机会干预和注入 DistributionService。
2. 即使它可能会干扰,它也会失败,因为您试图在构造函数中使用“distributionService”对象。字段注入只有在对象被构造后才会起作用。

现在关于解决问题。
长答案短 - 不要期望在您的 POJO 中自动注入。
通常,像您的 DevicesPojo 这样动态创建的对象中的“distributionService”之类的依赖项是完全避免的。
如果您坚持使用它们,请在构建时手动注入它们:

class DevicesPojoFactory {
    @Autowired @Qualifier("uniformDistribution") 
    private DistributionService uniformDistribution;
    ObjectMapper mapper = new ObjectMapper();

    DevicesPojo[] readFromFile(String path) {
         DevicesPojo[] devicePojoArr = mapper.readValue(...);
         for (DevicesPojo dp: devicePojoArr) {
              dp.setDistribution(uniformDistribution);
         }
    }
}

【讨论】:

  • 我可以在 devicedeserializer 中自动连接分发服务并从那里创建 devicespojo 的实例吗?
  • '在构造对象后发生字段注入'是有道理的。这也是我认为可能是错误的。但出于某种希望,我尝试了它。现在很清楚了。谢谢
  • 不确定 DeviceDeserializer 因为它的实例将由对 Spring 一无所知的 JSON 创建。仅仅封装 JSON 就容易多了。
  • 反序列化器的效果不佳。但我以某种方式解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 2020-01-24
  • 1970-01-01
  • 2016-09-20
相关资源
最近更新 更多