我在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),工作正常。
对于由 Spring 自动装配的 bean,该 bean 必须是 Spring bean(即在 context.xml 文件中声明或使用 Spring 注解进行注解(
@Service
、@Component
等)。
当然,它必须由 Spring 实例化,而不是由您的代码实例化。如果您使用
new
自己实例化一个 Spring bean,Spring 并不知道该 bean,也不会向其中注入任何内容。
Spring只是自动装配上下文的bean,没有通过new创建实例。但是为什么你在
uService
中声明 AddFriendInMyFriendListTask
而不是作为外部(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 属性)
如果您需要自动装配新创建的实例(没有容器支持),请调用
ctx.getAutowireCapableBeanFactory().autowireBean(实例)
其中 ctx 是您的 ApplicationContext,instance 是新创建的实例。
我问了类似的问题这里
另一种解决方案是将用户 IUserService 注入到 spring 管理的组件(服务、组件等)中,并将注入的值传递给类 AddFriendInMyFriendListTask 的构造函数。
因此,构造函数就变成了这样
public AddFriendInMyFriendListTask(User aA, User bB, IUserService userService) {
a = aA;
b = bB;
this.userService = userService;
}
并从 AddFriendInMyFriendListTask 类中删除
@Autowired
。
有一个类似的问题必须在服务中自动装配并传递给通过构造函数实现可运行的方法。
ctx.getAutowireCapableBeanFactory().autowireBean(instance) 对我有用