[英]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.