【问题标题】:Spring not autowiring field in a class with constructorSpring没有在具有构造函数的类中自动装配字段
【发布时间】:2016-05-02 05:41:27
【问题描述】:

我在 stackoverflow 中读过一些问题,例如:

我还阅读了这些问题中提供的链接,例如3.9.3 Fine-tuning annotation-based autowiring with qualifiers,但我尝试过的都没有。

这是我的课:

public class UmbrellaRestClient implements UmbrellaClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(UmbrellaRestClient.class);
    private static final Map<String, String> PARAMETROS_INFRA_UMBRELLA = ApplicationContextProvider.getApplicationContext().getBean(ParametrosInfraComponent.class)
            .findByIdParametroLikeAsMap("%UMBRELLA%");

    private final HttpConnectionRest conexaoHttp;

    @Autowired
    @Qualifier
    private TemplateLoaderImpl templateLoader;

    public UmbrellaRestClient(final String url) {
        this.conexaoHttp = new HttpConnectionRest(UmbrellaRestClient.PARAMETROS_INFRA_UMBRELLA.get("UMBRELLA_HOST") + url, "POST", true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String enviarNfe(final String cnpjFilial, final String idPedido, final BigDecimal valorGNRE, final String arquivoNfe) {
        if (StringUtils.isBlank(arquivoNfe)) {
            throw new ClientException("Arquivo de NF-e não carregado.");
        }

        final String usuario = StringUtils.defaultIfBlank(UmbrellaRestClient.PARAMETROS_INFRA_UMBRELLA.get("USUARIO_UMBRELLA"), "WS.INTEGRADOR");

        Map<String, String> parametrosTemplate = new HashMap<>(6);
        parametrosTemplate.put("usuario", usuario);
        parametrosTemplate.put("senha", StringUtils.defaultIfBlank(UmbrellaRestClient.PARAMETROS_INFRA_UMBRELLA.get("SENHA_UMBRELLA"), "WS.INTEGRADOR"));
        parametrosTemplate.put("valorGNRE", valorGNRE.toPlainString());
        parametrosTemplate.put("idPedido", idPedido);
        parametrosTemplate.put("cnpjFilial", cnpjFilial);
        parametrosTemplate.put("arquivoNfe", arquivoNfe);

        final String xmlRequisicao = ConverterUtils.retornarXMLNormalizado(this.templateLoader.preencherTemplate(TemplateType.ENVIO_XML_NFE, parametrosTemplate));

        this.conexaoHttp.setXmlEnvio(xmlRequisicao);

        UmbrellaRestClient.LOGGER.info("XML ENVIO #####################: {}", xmlRequisicao);

        return this.conexaoHttp.enviarXML();
    }
}

字段 templateLoader 没有被注入。我在其他具有依赖注入和工作的类中进行了测试。我猜这是因为我有一个依赖于参数的构造函数,并且这个参数实际上是由每个需要使用它的类传递的,所以我不能对 applicationContext 中的构造函数参数使用依赖注入。

我应该怎么做才能注入字段?

【问题讨论】:

  • 不要自己构造实例,spring只会在bean和它控制的实例中注入依赖。
  • 你能发布一个关于如何做的答案吗?
  • 听起来你真正需要的是一个注入了templateLoader工厂,它有一个采用url 并返回服务对象的方法。

标签: java spring spring-mvc dependency-injection


【解决方案1】:

在 Spring 框架中使用 Rest API 需要以不同的方式处理。这是简要说明。

Spring 是一个框架,它维护组件 bean 的生命周期,并从 bean 创建到它们的销毁全权负责。

REST API 还负责维护它们创建的 Web 服务的生命周期。

因此,Spring 和 REST 容器独立工作以有效管理它们创建的组件。

在我最近的项目中,我通过创建一个实现 Spring 的 ApplicationContextAware 接口的单独类并在 HashMap 中收集 bean 来使用这两种技术。可以从 REST 上下文静态访问此资源。

这方面的弱点是我们必须使用 beans.xml 文件并注册 beans,并在实现 ApplicationContextAware 接口的类中按名称获取 beans 等。

【讨论】:

    【解决方案2】:

    创建 Spring 控制的 bean 最简单的方法是直接通过ApplicationContext:

    @Autowired
    private ApplicationContext context;
    
    private UmbrellaRestClient getNewUmbrellaRestClient(String url) {
      return context.getBean("umbrellaRestClient", new Object[]{url});
    }
    

    基本上这是一个工厂方法。为此,必须将 UmbrellaRestClient 声明为范围 prototype 的 bean。因为所有具有非默认构造函数的 bean 都必须是作用域原型。

    如果类在组件扫描的包中,这就足够了:

    @Service
    @Scope("prototype")
    public class UmbrellaRestClient implements UmbrellaClient {
        ...
    

    【讨论】:

      猜你喜欢
      • 2012-05-06
      • 1970-01-01
      • 2017-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-23
      • 1970-01-01
      相关资源
      最近更新 更多