@Autowired在@Service?

时间:2014-05-07 14:03:19

标签: java spring

我无法让@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,则无法自动装配搜索者。困惑我的大脑; - )

有人可以提供帮助吗?

[编辑]

  • 组件扫描包括我的服务,控制器和所有内容,只需选中。
  • 我之前的界面确实不是很好(旧习惯)
  • 不确定这是否是&#34;重复&#34;问题,主要是因为我没有做任何事情&#34; new&#34;,我让春天做所有艰苦的工作,但我会更好地窥视。

4 个答案:

答案 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个解决方案

  1. 将代码从构造函数移动到使用@PostConstruct
  2. 注释的方法
  3. 更改默认的no-arg构造函数以获取参数,并使用它来执行依赖注入,而不是@Autowired field
  4. 解决方案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();
    }
}