我无法让@Autowired在@Service注释的类中工作,自动装配的变量总是为空。让我解释一下:
@Service
public class Searcher extends Thread implements ISearcher {
@Autowired
protected ISessionProvider sessionProvider; <-- always null
...
public Searcher() {
sessionProvider.doSomeStuff();
}
sessionProvider此处始终为null。
奇怪的是@Controller中的相同autowire确实有效:
@Controller
@RequestMapping("/search")
@Secured({ "ROLE_USER" })
public class SearchController extends BaseController {
@Autowired
protected ISessionProvider sessionProvider; <-- does work
@Autowired
protected ISearcher searcher;
最后一行抛出异常,因为Searcher的构造函数(实现ISearcher)试图访问sessionProvider,它是null。
我不确定我可能做错了什么,看起来Spring并没有自动装配Searcher中的ISessionProvider。
可能是春天首先在SearchController中自动装配Searcher,但它应首先在Searcher中自动装配SessionProvider,然后在SearchController中自动装配Searcher。如果没有有效的SessionProvider,则无法自动装配搜索者。困惑我的大脑; - )
有人可以提供帮助吗?
[编辑]
答案 0 :(得分:7)
Spring将首先创建bean实例,然后注入bean。您正在尝试在创建当前bean时访问注入的bean,因此bean将为null
。这是默认行为。
如果您希望/需要在创建bean之后执行任何逻辑,请使用@PostConstruct
修饰方法,该方法在创建bean并注入所有依赖项后调用。这是一个示例:
@Service
public class Searcher extends Thread implements ISearcher {
@Autowired
protected ISessionProvider sessionProvider;
public Searcher() {
//nothing should be here...
}
@PostConstruct
public void init() {
sessionProvider.doSomeStuff();
}
}
答案 1 :(得分:5)
Spring只能在构造bean之后执行依赖注入。您正在构造函数中调用该方法,此时ISessionProvider
尚未注入,因此它是null
,这反过来会导致一个不错的NullPointerException
。
你有2个解决方案
@PostConstruct
@Autowired field
。 解决方案1:将该代码移至使用@PostConstruct
注释的方法。
@Service
public class Searcher extends Thread implements ISearcher {
@Autowired
protected ISessionProvider sessionProvider;
...
public Searcher() {}
@PostConstruct
public void init() {
sessionProvider.doSomeStuff();
}
解决方案2:使用基于构造函数的依赖注入。
@Service
public class Searcher extends Thread implements ISearcher {
protected final ISessionProvider sessionProvider;
@Autowired
public Searcher(ISessionProvider sessionProvider) {
this.sessionProvider=sessionProvider;
sessionProvider.doSomeStuff();
}
}
答案 2 :(得分:1)
我没有进行测试,但我认为问题是,在类Searcher
中,您创建了一个无参数的构造函数,并且您使用了#34; autowired&#34;豆。我想你会得到NPE。如果你没有指定一个,那么spring将使用默认构造函数(通过反射)实例化你的Searcher
,也就是说,它将使用你创建的无参数构造函数,但此时,&#34 ;自动装配Autowired&#34;豆子还没有注射。
如果要在实例化bean之后立即执行某些操作,可以将逻辑代码包装在方法中,并使用@PostConstruct
对其进行注释。
答案 3 :(得分:0)
我也遇到同样的问题,但是我不能使用@PostConstruct
,因为我没有使用doinit
。我有一个简单的方法是从lang服务获取语言。
我的lang服务在这里null
,但在另一个控制器中不是null
,它正在自动连接。
@Service
@Configurable(preConstruction = true, autowire = Autowire.BY_NAME)
public class FormSelectLanguageHandler extends SimpleTagSupport {
@Autowired
private LangService langService;
public List<Lang> getLanguages(){
Sessions session = (Sessions) getJspContext().findAttribute("SHLSESSION");
List<Lang> languages=new ArrayList<Lang>();
//List<Lang> allLanguages = langService.findAllLangs();
List<Lang> all =new ArrayList<Lang>();
if (isRenderLangLabel()) {
all = langService.findByDisplayOrderAsc();
} else {
all = langService.findByNameOrderByNameAsc();
}
Long companyId = (null == session || null == session.getCompany())? null:session.getCompany().getId();
}
}