简体   繁体   English

Spring没有使用构造函数自动装配类中的字段

[英]Spring not autowiring field in a class with constructor

I've read questions here in stackoverflow such as: 我在这里阅读了stackoverflow中的问题,例如:

I've also read links provided in these questions such as 3.9.3 Fine-tuning annotation-based autowiring with qualifiers but nothing that I tried worked. 我还阅读了这些问题中提供的链接,例如3.9.3使用限定符对基于注释的自动装配进行微调,但没有任何尝试。

Here's my class: 这是我的课:

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();
    }
}

The field templateLoader does not get injected. 字段templateLoader不会被注入。 I tested in other classes that have dependency injection and works. 我在其他具有依赖项注入并且可以正常工作的类中进行了测试。 I guess this is happening because I have a constructor that depends on a parameter and this parameter is really passed by each class that needs to use it so I cannot use dependency injection to the parameter of the constructor in applicationContext for example. 我猜发生了这种情况,因为我有一个依赖于参数的构造函数,并且每个需要使用它的类实际上都传递了该参数,因此,例如,我不能在applicationContext中对构造函数的参数使用依赖项注入。

What should I do to get field injected? 我该怎么做才能注入电场?

Using Rest APIs with Spring framework needs to be handled differently. 将Rest API与Spring框架一起使用需要进行不同的处理。 Here is brief explanation. 这里是简要说明。

Spring is a framework that maintains the lifecycle of the component beans and is fully responsible from bean creation to their destruction. Spring是一个框架,用于维护组件bean的生命周期,并从创建bean到销毁bean负全责。

REST APIs are also responsible for maintaining the life cycle of the web services they create. REST API还负责维护其创建的Web服务的生命周期。

So, Spring and REST container are working independently to manage the components they have created effeciently. 因此,Spring和REST容器正在独立工作,以管理它们有效创建的组件。

In my recent project what I did to use both technologies, by creating a seperate class which implements Spring's ApplicationContextAware interface, and collect the beans in a HashMap . 在我最近的项目中,我通过创建一个单独的类来实现这两种技术,该类实现了Spring的ApplicationContextAware接口,并将这些bean收集在HashMap This resource can be accessed statically from REST contexts. 可以从REST上下文静态访问此资源。

The weak point about this is we have to use beans.xml file and register the beans and in the class that implements ApplicationContextAware interface getting the beans by name etc. 弱点是我们必须使用beans.xml文件并注册bean,并在实现ApplicationContextAware接口的类中按名称等获取bean。

The easiest way to create a Spring controlled bean is directly through the ApplicationContext : 创建Spring受控bean的最简单方法是直接通过ApplicationContext

@Autowired
private ApplicationContext context;

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

Basically this is a factory method. 基本上,这是工厂方法。 For this to work the UmbrellaRestClient must be declared a bean of scope prototype . 为此,必须将UmbrellaRestClient声明为作用域prototype的bean。 As all beans that have a non default constructor must be of scope prototype. 因为所有具有非默认构造函数的bean都必须是作用域原型。

In the case where the class is in a package that is component scanned, this will suffice: 如果该类在经过组件扫描的包中,则可以满足:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM