簡體   English   中英

Spring依賴注入在單例類中不起作用

[英]Spring Dependency Injection not working in singleton class

我做了一個名為 AcessoCliente 的單例類

public class AcessoCliente {

    private HashMap<String, Cliente> clientes;
    private new HashMap<String, Date> clientesNaoEncontrados;

    private static AcessoCliente instance;

    static {
        instance = new AcessoCliente();
    }

    public static AcessoCliente get() {
        return instance;
    }

    private AcessoCliente() {
        clientes = new HashMap<String, Cliente>();
        clientesNaoEncontrados = new HashMap<String, Date>();
    }

    /*business*/
}

但是我需要在我的單例類上對一個名為 ValidadorNivelDeAcessoBusiness 的類進行依賴注入

@Component
public class ValidadorNivelDeAcessoBusiness {

    @Autowired
    QuerysNiveisDeAcesso querysNiveisDeAcesso;
    /*business*/
}

我正在嘗試執行此依賴項注入但不起作用,這就是我所做的:

public class AcessoCliente {

    @Autowired
    ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness;

    private HashMap<String, Cliente> clientes;
    private new HashMap<String, Date> clientesNaoEncontrados;

    private static AcessoCliente instance;

    static {
        ApplicationContext context = new AnnotationConfigApplicationContext(AcessoCliente.class);
        instance = context.getBean(AcessoCliente.class);
    }

    public static AcessoCliente get() {
        return instance;
    }

    private AcessoCliente() {
        clientes = new HashMap<String, Cliente>();
        clientesNaoEncontrados = new HashMap<String, Date>();
    }

    /*business*/
}

但依賴注入不起作用,我收到此錯誤:

創建名為“acessoCliente”的 bean 時出錯:通過字段“validadorNivelDeAcessoBusiness”表達的不滿意依賴; 嵌套異常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:沒有可用的“my.project.business.interceptorBusiness.ValidadorNivelDeAcessoBusiness”類型的合格 bean:預計至少有 1 個 bean 有資格作為自動裝配候選。
依賴注解:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

編輯1。 那是 QuerysNiveisDeAcesso 類

@Component
public class QuerysNiveisDeAcesso extends QuerysClientes {

    public QueryIntegratorBuilder queryBuscaNiveisDeAcesso(String[] condicoesQuery) throws Exception {
        return super.executaQuery("BUSCA_NIVEIS_DE_ACESSO", condicoesQuery);
    }

    public QueryIntegratorBuilder queryBuscaNiveisDeAcesso() throws Exception {
        return super.executaQuery("BUSCA_NIVEIS_DE_ACESSO");
    }

    public QueryIntegratorBuilder queryBuscaNiveisDeAcesso(String sqlWhere, String[] condicoesQuery) throws Exception {
        return super.executaQuery("BUSCA_NIVEIS_DE_ACESSO", condicoesQuery, sqlWhere);
    }

}

您正在嘗試混合使用 Java 單例和 Spring 單例。

為了使其與純 java 和 spring 兼容,您應該在參數中使用注入的服務創建靜態工廠方法,並在@Configuration 文件中創建一個單例 bean。

public class AcessoCliente {

  ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness;

  private HashMap<String, Cliente> clients;
  private HashMap<String, Date> clientesNaoEncontrados;

  private static AcessoCliente instance;

  public static AcessoCliente getInstance(ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness) {
    if(instance == null) {
      instance = new AcessoCliente(validadorNivelDeAcessoBusiness);
    }
    return instance;
  }

  private AcessoCliente(ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness) {
    clientes = new HashMap<String, Cliente>();
    clientesNaoEncontrados = new HashMap<String, Date>();
    this.validadorNivelDeAcessoBusiness = validadorNivelDeAcessoBusiness;
  }
}

@Configuration
public class AcessoClienteConfiguration
{    
  @Bean
  @Scope("singleton")
  public AcessoCliente acessoCliente(ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness)
  {
    return AcessoCliente.getInstance(validadorNivelDeAcessoBusiness);
  }
}

我試圖重新創建您遇到的相同問題,似乎您在ValidadorNivelDeAcessoBusiness類中的依賴項正在嘗試加載,但是此類中的一個字段可能缺少@Component批注,以便加載 Spring 應用程序上下文.

@Component public class AcessoCliente {
    @Autowired
    ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness;
}

@Component
public class ValidadorNivelDeAcessoBusiness {

   @Autowired
   QuerysNiveisDeAcesso querysNiveisDeAcesso;
}

public class QuerysNiveisDeAcesso {
   // some code
}

會產生上述錯誤: 'acessoCliente': Unsatisfied dependency expressed through field 'validadorNivelDeAcessoBusiness'

確保ValidadorNivelDeAcessoBusiness中的所有字段都有一個@Component使 spring 應用程序上下文正常工作,即:

@Component 
public class QuerysNiveisDeAcesso {
      // some code
}

你完全誤用了 spring 的目的。

首先,在AcessoCliente類中創建應用程序上下文毫無意義。

應用程序上下文是一個“全局”的 spring 注冊表對象,通常在整個應用程序中存在一次。

如果您使用的是普通 Spring - 您可以直接在public static void main方法中創建應用程序上下文。 然后從那里拿豆子。

接下來,當您創建應用程序上下文時,您應該將配置對象而不是單個類傳遞給它。 您還可以使用組件掃描,有很多技術。 但總而言之,它應該接受配置的“規則” - 讀取查找並加載 bean。

現在讓我們回到AccessCliente類。 您已將其定義為具有靜態方法和私有構造函數的單例,這沒問題。 但它不適用於 spring——事實上,如果你使用的是 spring,你可以使這個類成為單例,在整個應用程序上下文中將有一個 bean。 這更易於管理和清晰(+ 沒有樣板代碼)。 事實上,默認情況下所有 bean 都是 spring 宇宙中的單例。

接下來要提到的是,當您制作一個單例bean (一個實例由 spring 管理的類)時,整個自動裝配魔法將自動開始工作。

您所做的是一個奇怪的混合體,無論如何都不起作用(如果沒有指示,spring 如何創建一個 bean,即使是這樣,構造函數也是私有的)。

所以,回顧一下,你需要這樣的東西:

public class Main {
   public static void main(String  [] args) {
     ApplicationContext ctx = ...;
     ctx.getBean(SomeClassThatStartsTheFlow.class).doSomething();
   }    
}

@Service
public class AcessoCliente {

    @Autowired
    ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness;

    private HashMap<String, Cliente> clientes;
    private new HashMap<String, Date> clientesNaoEncontrados;

    public AcessoCliente() {
        clientes = new HashMap<String, Cliente>();
        clientesNaoEncontrados = new HashMap<String, Date>();
    }

    /*business*/
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM