Java Spring依赖项注入在singleton类中不起作用
我做了一个名为AcessoCliente的单人课Java Spring依赖项注入在singleton类中不起作用,java,spring,dependency-injection,autowired,Java,Spring,Dependency Injection,Autowired,我做了一个名为AcessoCliente的单人课 public class AcessoCliente { private HashMap<String, Cliente> clientes; private new HashMap<String, Date> clientesNaoEncontrados; private static AcessoCliente instance; static { instance
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*/
}
我正在尝试进行依赖注入,但不起作用,我就是这么做的:
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*/
}
你完全误用了春天的意义 首先,在
acessoclient
类中创建应用程序上下文没有意义
应用程序上下文是一个“全局”spring注册表对象,通常在整个应用程序中存在一次
如果您使用的是纯Spring,那么就可以在publicstaticvoidmain
方法中创建应用程序上下文。然后从那里得到豆子
接下来,在创建应用程序上下文时,应该向其传递配置对象,而不是单个类。您还可以使用组件扫描,有许多技术。但总而言之,它应该接受配置-读取-查找和加载bean的“规则”
现在让我们回到AccessCliente
类。您已经将它定义为一个具有静态方法和私有构造函数的单例,没关系。但是它不适用于spring——事实上,如果您使用spring,您可以将这个类设置为一个单例,因为在整个应用程序上下文中只有一个bean。
这是更易于管理和清晰的(+没有样板代码)。
事实上,默认情况下,SpringUniverse中的所有bean都是单例
接下来要提到的是,当您创建一个singletonbean(一个实例由spring管理的类)时,整个自动布线魔术将自动开始工作
您所做的是一个奇怪的混合体,无论如何都不会工作(如果spring没有被指示创建bean,那么它如何创建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*/
}
公共类主{
公共静态void main(字符串[]args){
ApplicationContext ctx=。。。;
getBean(someclassthattstartsofflow.class).doSomething();
}
}
@服务
公共类Acesso客户{
@自动连线
ValidadorNivelDeacesso业务ValidadorNivelDeacesso业务;
私人HashMap客户;
私人新HashMap客户NoeContrados;
公共ACESSOCLIENT(){
clientes=newhashmap();
clientesNaoEncontrados=新HashMap();
}
/*生意*/
}
我试图重新创建与您相同的问题,您在ValidadorNivelDeacessBusiness
类中的依赖项似乎正在尝试加载,但是该类中的一个字段可能缺少@组件
注释,无法加载Spring应用程序上下文
@Component public class AcessoCliente {
@Autowired
ValidadorNivelDeAcessoBusiness validadorNivelDeAcessoBusiness;
}
@Component
public class ValidadorNivelDeAcessoBusiness {
@Autowired
QuerysNiveisDeAcesso querysNiveisDeAcesso;
}
public class QuerysNiveisDeAcesso {
// some code
}
将产生上述错误:“AcessClient”:通过字段“ValidOrniveLDeAcessoBusiness”表示的未满足的依赖关系
确保ValidadorNivelDeAcessoBusiness
中的所有字段都有@组件
使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);
}
}
公共类AcessClient{
ValidadorNivelDeacesso业务ValidadorNivelDeacesso业务;
私有HashMap客户端;
私有HashMap客户端NoeContrados;
私有静态acessoclient实例;
公共静态AcessClient getInstance(ValidadorNivelDeacessBusiness ValidadorNivelDeacessBusiness){
if(实例==null){
实例=新AcessClient(ValidadorNivelAcessBusiness);
}
返回实例;
}
私人Acesso客户(ValidOrnivelAcesso业务ValidOrnivelAcesso业务){
clientes=newhashmap();
clientesNaoEncontrados=新HashMap();
this.validadorNivelDeAcessoBusiness=validadorNivelDeAcessoBusiness;
}
}
@配置
公共类AcessClient配置
{
@豆子
@范围(“单例”)
公共ACESSOCLIENT ACESSOCLIENT(有效或无效ACESSOBUSINESS有效或无效ACESSOBUSINESS)
{
返回acesscliente.getInstance(validadorNivelDecessObusiness);
}
}
这个类是什么:QuerysNiveisDeAcesso?@Ismail QueryNiveisDeAcesso在postIn addition中添加,在春季,我们用@Scope(“singleton”)注释标记singleton组件。但是,由于@Service default scope已经是singleton,我们这里不需要它。谢谢,但是在您制作的这个示例中,AcessClient类是一个Spring singleton,但是Spring作用域的singleton与设计模式singleton不同。在您的实现中,如果我在两个不同的对象中进行AcessClient依赖项注入,spring go将实例化两个不同的AcessClient对象?不,只有一个对象(实例)注入两个不同的对象。这就是春天单身的意义所在。一般来说,如果您使用的是单例,那么就不需要使用java单例,这些单例用于遗留应用程序或在没有依赖注入容器的情况下编写的应用程序中
@Component
public class QuerysNiveisDeAcesso {
// some code
}
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);
}
}