【问题标题】:Spring Autowired service is nullSpring Autowired 服务为空
【发布时间】:2017-04-21 08:27:37
【问题描述】:

我有调用 Presenter 来获取一些数据的 RestController 类。

@RestController
@RequestMapping(value="notes/api")
public class NotesRestController {

private GetAllNotesPresenter getAllNotesPresenter;

@RequestMapping(value="/all")
public List<Note> getAll(){
    getAllNotesPresenter = new GetAllNotesPresenterImpl();
    return getAllNotesPresenter.getAll();
}

}

在 Presenter 类中我调用 DataSource(不是 Spring Repository,只是 DAO 类)。

public class GetAllNotesPresenterImpl implements GetAllNotesPresenter {

private NotesDataSource dataSource;
private NotesRepository repository;

public GetAllNotesPresenterImpl(){

    dataSource = new DatabaseDataSource();
    repository = new NotesRepositoryImpl(dataSource);
}
@Override
public List<Note> getAll() {
    return repository.getAll();
}

}

这是我的 Repository 类,它不是 Spring Repository,它只是 DAO 类。

public class NotesRepositoryImpl implements NotesRepository {

private NotesDataSource dataSource;

public NotesRepositoryImpl(NotesDataSource dataSource){
    this.dataSource = dataSource;
}

@Override
public List<Note> getAll() {
    return dataSource.getAll();
}

}

这是我的服务类:

@Service
@Transactional
public class NotesServiceImpl implements NotesService {

@Autowired
private NotesJpaRepository repository;

@Override
public List<NoteJpa> getAll() {
    return repository.findAll();
}

}

在DataSource类里面我想做@Autowire的Spring服务,但是我得到空指针异常。服务总是空的。

@Component
public class DatabaseDataSource implements NotesDataSource {

@Autowired
private NotesService notesService;

public DatabaseDataSource(){
}

@Override
public List<Note> getAll() {
    return notesService.getAll();
}

}

【问题讨论】:

  • 如果上面的代码是正确的,我猜NotesService 将永远不会被构造(并且之前抛出异常),因为它期望NotesJpaRepository 你要么没有提到要么不是一个bean .如果这应该是 NotesRepository 的实现,它必须被实例化并作为 bean 公开。
  • NotesService接口有@Service注解吗?

标签: java spring spring-boot spring-data spring-data-jpa


【解决方案1】:

即使您将DatabaseDataSource 注释为@Component,您也没有注入,因此沿途将其用作Spring Bean。您只需手动创建它:

public GetAllNotesPresenterImpl(){

    dataSource = new DatabaseDataSource();
    repository = new NotesRepositoryImpl(dataSource);
}

为了利用这个bean的注入:

@Autowired
private NotesService notesService;

您需要从顶部开始使用 Spring 注入(这只是您可以使用的方法之一):

1)在控制器中注入dataSource:

@RestController
@RequestMapping(value="notes/api")
public class NotesRestController {

private GetAllNotesPresenter getAllNotesPresenter;

@Autowired
private NotesDataSource dataSource;

@RequestMapping(value="/all")
public List<Note> getAll(){
    getAllNotesPresenter = new GetAllNotesPresenterImpl(dataSource);
    return getAllNotesPresenter.getAll();
}

2)更改GetAllNotesPresenterImpl的构造函数:

public GetAllNotesPresenterImpl(NotesDataSource dataSource){

    this.dataSource = dataSource;
    repository = new NotesRepositoryImpl(dataSource);
}

其他选项是将GetAllNotesPresenterImplNotesRepositoryImpl 作为spring bean 并直接在NotesRepositoryImpl 中注入数据源。最终决定权由您决定。

【讨论】:

  • 是的,这可行:) 我需要一些解释。如果我有多个 NotesDataSource 的实现会发生什么。目前我只有 DatabaseDataSource 实现了在我的 RestController 类中注入的 NotesDataSoruce 接口。
  • 您将使用@Qualifier 注释来指定您明确希望用于注入的实现。
  • 谢谢!如果您愿意,您可以添加它,也许可以举个例子,因为很多人都在搜索这类问题。它可能对某人有用。
  • 你能写出如何实现你提到的其他选项吗?我试过但失败了。谢谢
  • 我只会用太多东西污染帖子。一般的想法是使用@Service 将其他类制作成bean。多亏了这一点,您不需要将数据源注入控制器,而是直接注入存储库,而无需通过这么多层。
猜你喜欢
  • 2022-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-31
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
相关资源
最近更新 更多