Spring 依赖注入在单例中不起作用 class
Spring Dependency Injection not working in singleton class
我做了一个名为 AcessoCliente
的单例 class
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 的 class 进行依赖注入 class
@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*/
}
但是依赖项注入不起作用,我收到此错误:
Error creating bean with name 'acessoCliente': Unsatisfied dependency expressed through field 'validadorNivelDeAcessoBusiness'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'my.project.business.interceptorBusiness.ValidadorNivelDeAcessoBusiness' available: expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
编辑1。那就是 QuerysNiveisDeAcesso class
@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);
}
}
您完全误用了 spring 的目的。
首先,在 AcessoCliente
class.
中创建应用程序上下文没有意义
应用程序上下文是一个“全局”spring 的注册表对象,通常在整个应用程序中只存在一次。
如果您使用的是 Plain Spring - 您可以在 public static void main
方法中创建应用程序上下文。然后从那里得到豆子。
接下来,当您创建应用程序上下文时,您应该将配置对象传递给它,而不是单个 class。您还可以使用组件扫描,有很多技术。但总而言之,它应该接受“规则”来配置 - 阅读查找并加载 beans。
现在让return到AccessCliente
class。您已将其定义为具有静态方法和私有构造函数的单例,没关系。但它不适用于 spring - 事实上,如果你使用 spring,你可以使这个 class 成为单例,从某种意义上说,整个中只有一个 bean应用上下文。
这更易于管理和清晰(+ 没有样板代码)。
事实上,在 spring 宇宙中,默认情况下所有 bean 都是单例。
接下来要提到的是当你创建一个单例bean(一个class,它的实例由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*/
}
我已尝试重现您遇到的相同问题,似乎您在 ValidadorNivelDeAcessoBusiness
class 中的依赖项正在尝试加载,但是此 [=23] 中的字段之一=] 可能缺少 @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
}
您正在尝试混合 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);
}
}
我做了一个名为 AcessoCliente
的单例 classpublic 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 的 class 进行依赖注入 class
@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*/
}
但是依赖项注入不起作用,我收到此错误:
Error creating bean with name 'acessoCliente': Unsatisfied dependency expressed through field 'validadorNivelDeAcessoBusiness'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'my.project.business.interceptorBusiness.ValidadorNivelDeAcessoBusiness' available: expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
编辑1。那就是 QuerysNiveisDeAcesso class
@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);
}
}
您完全误用了 spring 的目的。
首先,在 AcessoCliente
class.
应用程序上下文是一个“全局”spring 的注册表对象,通常在整个应用程序中只存在一次。
如果您使用的是 Plain Spring - 您可以在 public static void main
方法中创建应用程序上下文。然后从那里得到豆子。
接下来,当您创建应用程序上下文时,您应该将配置对象传递给它,而不是单个 class。您还可以使用组件扫描,有很多技术。但总而言之,它应该接受“规则”来配置 - 阅读查找并加载 beans。
现在让return到AccessCliente
class。您已将其定义为具有静态方法和私有构造函数的单例,没关系。但它不适用于 spring - 事实上,如果你使用 spring,你可以使这个 class 成为单例,从某种意义上说,整个中只有一个 bean应用上下文。
这更易于管理和清晰(+ 没有样板代码)。
事实上,在 spring 宇宙中,默认情况下所有 bean 都是单例。
接下来要提到的是当你创建一个单例bean(一个class,它的实例由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*/
}
我已尝试重现您遇到的相同问题,似乎您在 ValidadorNivelDeAcessoBusiness
class 中的依赖项正在尝试加载,但是此 [=23] 中的字段之一=] 可能缺少 @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
}
您正在尝试混合 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);
}
}