java 为什么自动装配在线程中不起作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7405232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:49:19  来源:igfitidea点击:

Why does Autowiring not function in a thread?

javamultithreadingspringtaskautowired

提问by user942458

I've made a maven project in Spring 3.0, I've made some DAO, services and controllers, in one of mine controller I call a service in which I start a thread, the problem is that in the thread I declare a "service variable" that should be initialized with Autowired annotiation, but it doesn't work and the variable isn't initilized and has the value null.

我在 Spring 3.0 中做了一个 maven 项目,我做了一些 DAO、服务和控制器,在我的一个控制器中我调用了一个服务,我在其中启动了一个线程,问题是在线程中我声明了一个“服务变量”,应该用 Autowired 注释初始化,但它不起作用,变量没有初始化并且值为 null。

this is the thread class

这是线程类

package com.project.tasks;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;

import com.project.entities.user.User;
import com.project.services.IUserService;

@Component
public class AddFriendInMyFriendListTaskExecutor {
private class AddFriendInMyFriendListTask implements Runnable {


     // HERE IS THE PROBLEM
    @Autowired
    private IUserService uService;

    private User a;
    private User b;

    public AddFriendInMyFriendListTask() {
        ;
    }

    public AddFriendInMyFriendListTask(User aA, User bB) {
        a = aA;
        b = bB;
    }

    public User getA() {
        return a;
    }
    public void setA(User a) {
        this.a = a;
    }
    public User getB() {
        return b;
    }
    public void setB(User b) {
        this.b = b;
    }


    public void run() {
                    // FROM HERE IT PRINTS THE VALUE OF uService THAT IS NULL
        System.out.println("uService:" + uService);
        uService.insertRightUserIntoLeftUserListOfFriends(a, b);
    }
}

private TaskExecutor taskExecutor;

  public AddFriendInMyFriendListTaskExecutor(TaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
  }

  public void doIt(User a, User b) {
      taskExecutor.execute(new AddFriendInMyFriendListTask(a, b));
  }
}

this is the piece of code that calls the thread

这是调用线程的一段代码

    User a = uDao.getUser(hrA.getMyIdApp());
    User b = uDao.getUser(hrA.getOtherIdApp());
    SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
    AddFriendInMyFriendListTaskExecutor tmp = new AddFriendInMyFriendListTaskExecutor(taskExecutor);
    tmp.doIt(a, b);

I'd like to highlight that in all the other tests in which I don't call any threads, the Autowired of a UserService instance functions correctly! The method I call: insertRightUserIntoLeftUserListOfFriends(User a, User b), works correctly.

我想强调的是,在我不调用任何线程的所有其他测试中,UserService 实例的 Autowired 功能正常!我调用的方法:insertRightUserIntoLeftUserListOfFriends(User a, User b),工作正常。

回答by JB Nizet

For a bean to be autowired by Spring, the bean must be a Spring bean (i.e. be declared in the context.xml file or be annotated with a Spring annotation (@Service, @Component, etc.).

对于要被Spring自动装配一个bean,bean必须是一个Spring bean(即在context.xml文件中声明或使用Spring的注释(进行标注@Service@Component等等)。

And of course, it must be instantiated by Spring, and not by your code. If you instantiate a Spring bean yourself with new, Spring doesn't know about the bean, and doesn't inject anything into it.

当然,它必须由 Spring 实例化,而不是由您的代码实例化。如果你自己实例化一个 Spring bean new,Spring 不知道这个 bean,也不会向它注入任何东西。

回答by Arne Burmeister

Spring just autowires beans of the context, no instances created by new. But why do you have declared uServicein AddFriendInMyFriendListTaskand not as a bean property of the outer (bean) class AddFriendInMyFriendListTaskExecutor, that should simply work:

Spring 只是自动装配上下文的 bean,没有由 new 创建的实例。但是为什么你已经声明uServiceinAddFriendInMyFriendListTask而不是作为外部 (bean) 类的 bean 属性AddFriendInMyFriendListTaskExecutor,这应该简单地工作:

@Component
public class AddFriendInMyFriendListTaskExecutor {

  private class AddFriendInMyFriendListTask implements Runnable {

    private final User a;
    private final User b;

    public AddFriendInMyFriendListTask(User aA, User bB) {
      a = aA;
      b = bB;
    }

    public void run() {
      AddFriendInMyFriendListTaskExecutor.this.uService.insertRightUserIntoLeftUserListOfFriends(a, b);
    }
  }

  @Autowired
  private IUserService uService;

  @Autowired
  private TaskExecutor taskExecutor;

  public void doIt(User a, User b) {
    taskExecutor.execute(new AddFriendInMyFriendListTask(a, b));
  }
}

(removed some unused getter/setter and made taskExecutor also a bean property)

(删除了一些未使用的 getter/setter 并使 taskExecutor 也是一个 bean 属性)

回答by stacker

If you need to autowire a newly created instance (without container support) invoke

如果您需要自动装配新创建的实例(没有容器支持),请调用

ctx.getAutowireCapableBeanFactory().autowireBean(instance)

ctx.getAutowireCapableBeanFactory().autowireBean(实例)

where ctx is your ApplicationContext and instance the newly created instance.

其中 ctx 是您的 ApplicationContext 和 instance 是新创建的实例。

I asked a similar question here

在这里问了一个类似的问题

回答by aseychell

Another solution would be to inject the user IUserService in a spring managed component (service, component, etc.) and pass the injected value to the constructor of the class AddFriendInMyFriendListTask.

另一种解决方案是将用户 IUserService 注入 Spring 管理的组件(服务、组件等)中,并将注入的值传递给类 AddFriendInMyFriendListTask 的构造函数。

Thus, the constructor becomes something like this

因此,构造函数变成了这样

public AddFriendInMyFriendListTask(User aA, User bB, IUserService userService) {
    a = aA;
    b = bB;
    this.userService = userService;
}

and remove the @Autowiredfrom the AddFriendInMyFriendListTask class.

@Autowired从 AddFriendInMyFriendListTask 类中删除。

回答by Xcoder

Had a similar issue had to Autowire in the service and pass to the method that implements runnable through the constructor.

有一个类似的问题不得不在服务中自动装配并传递给通过构造函数实现可运行的方法。