【问题标题】:Why does Autowiring not function in a thread?为什么自动装配在线程中不起作用?
【发布时间】:2011-11-16 08:11:31
【问题描述】:

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

这是线程类

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));
  }
}

这是调用线程的一段代码

    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);

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

【问题讨论】:

    标签: java multithreading spring task autowired


    【解决方案1】:

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

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

    【讨论】:

    • 没有。您使用 new AddFriendInMyFriendListTaskExecutor() 实例化 AddFriendInMyFriendListTaskExecutor,内部类 AddFriendInMyFriendListTask(应该是静态的)没有注释,并且您也使用 new 实例化它。
    • 对不起,我可能不明白你的答案,或者我无法解释我的问题,AddFriendInMyFriendListTaskExecutor 实例的创建并没有给我任何问题,事实上在代码之后:" AddFriendInMyFriendListTaskExecutor tmp = new AddFriendInMyFriendListTaskExecutor(taskExecutor);" tmp不为null,问题是当我在AddFriendInMyFriendListTask类中使用uService时,AddFriendInMyFriendListTask实例的calss和初始化都没有问题
    • Spring 必须实例化 spring bean。不是你。您不能使用 new 运算符来实例化 spring bean。它们必须要么由 Spring 注入到当前 bean 中,要么你必须从 bean factory 中获取。
    【解决方案2】:

    Spring 只是自动装配上下文的 bean,没有由 new 创建的实例。但是为什么你在AddFriendInMyFriendListTask 中声明了uService 而不是作为外部(bean)类AddFriendInMyFriendListTaskExecutor 的bean 属性,这应该可以正常工作:

    @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));
      }
    }
    

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

    【讨论】:

      【解决方案3】:

      如果你需要自动装配一个新创建的实例(不支持容器)调用

      ctx.getAutowireCapableBeanFactory().autowireBean(instance)

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

      我问过类似的问题here

      【讨论】:

        【解决方案4】:

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

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

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

        并从 AddFriendInMyFriendListTask 类中删除 @Autowired

        【讨论】:

          【解决方案5】:

          有类似的问题不得不在服务中Autowire并通过构造函数传递给实现runnable的方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-11-18
            • 2018-02-05
            • 1970-01-01
            • 2013-04-02
            • 2018-04-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多