扩展 CrudRepository 的 @Autowired 接口如何工作?我想有一些见解 [英] How does the @Autowired interface, which extends CrudRepository, works? I would like to have some insights

查看:36
本文介绍了扩展 CrudRepository 的 @Autowired 接口如何工作?我想有一些见解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我的接口扩展 CrudRepository 如下

 @Repository公共接口 EmployeeRepository 扩展 CrudRepository<Employee, Integer>{}

我在我的 Service 类中使用 EmployeeRepository 接口,如下所示

@Service公共类 EmployeeService{@自动连线员工存储库员工存储库;公共列表<员工>获取所有雇员(){列出<员工>listEmp=new ArrayList<员工>();employeeRepository.findAll().forEach(listEmp::add);返回列表Emp;}}

和控制器如下

@RestController公共类 WelcomeController{@自动连线EmployeeService 雇佣;@RequestMapping("/员工")公共列表<员工>获取雇员(){返回empservice.getAllEmployee();}}

它给出了以下异常

org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为welcomeController"的bean时出错:通过字段empservice"表示不满足的依赖关系:创建名为employeeService"的bean时出错:通过字段employeeRepository"表示不满意的依赖项'

错误很明显,因为接口EmployeeRepository没有被任何类实现并且

@Autowired员工存储库员工存储库;

Autowired 将失败,因为没有类正在实现 employeeRepository.

不过,我对它的工作原理感到困惑,因为我在 GitHub 和教程上看到的每个代码都运行良好.

我哪里出错了,@Autowired 如何在扩展 CrudRepository 的接口上工作,即使没有类实现它;自动装配的基本规则是什么?也就是说,如果您要自动装配任何接口,则至少有一个类必须实现该接口,然后自动装配才会成功.

解决方案

嗯,关于 Spring Data Repositories 确实已经有了很好的答案:Spring Data 存储库是如何实际实现的? .但是,在阅读您的问题时,我相信 @Autowired 的工作方式有些混乱.让我试着给出事件的高级顺序:

  1. 您将依赖项放在代码中的 EmployeeRepository 上:

    <代码>@自动连线私有 EmployeeRepository 雇员Repository;

  2. 通过执行步骤 (1),您向 Spring 容器指示在其 启动过程 期间它应该找到实现 EmployeeRepository 的类的实例并注入将其放入 @Autowired 注释的目标中.我想在此强调这样一个事实,即为了使注入正常工作,您应该在 在 Spring 容器中实现所需的接口 类的实例运行时而不是在编译过程中.

  3. 所以现在出现了一个合乎逻辑的问题:如果我们没有显式定义该类,那么在 Spring 容器的启动过程中,实现 UserRepository 的类在哪里出现?"p>

  4. 这是 Oliver 的详细回答:How areSpring Data 存储库实际实现了吗?.简而言之,Spring Data 在容器引导过程中扫描所有存储库接口;创建实现这些接口的新类(代理);将这些类的实例放入 Spring 容器中,这允许 @Autowired 像对容器中的任何其他 Spring bean 一样查找和注入它们.

同样,这些过程只有在您设置并正确配置了 Spring Data 时才有效,否则注入确实会失败.

希望这会有所帮助.

Suppose my interface extends CrudRepository as follows

 @Repository
    public interface EmployeeRepository extends CrudRepository<Employee, Integer> 
    {
    }

and I use the EmployeeRepository interface in my Service class as follows

@Service
public class EmployeeService 
{

 @Autowired 
  EmployeeRepository employeeRepository;


 public List<Employee> getAllEmployee()
 {
     List<Employee> listEmp=new ArrayList<Employee>();
     employeeRepository.findAll().forEach(listEmp::add);
     return listEmp;


 }
}

and controller as follows

@RestController
public class WelcomeController 
{
    @Autowired
    EmployeeService empservice;

    @RequestMapping("/employees")
    public List<Employee> getEmployees()
    {
        return empservice.getAllEmployee();
    }

}

and it gives the following exception

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'welcomeController': Unsatisfied dependency expressed through field 'empservice': Error creating bean with name 'employeeService': Unsatisfied dependency expressed through field 'employeeRepository'

The error is obvious because interface EmployeeRepository is not implemented by any class and

@Autowired  
EmployeeRepository employeeRepository;

Autowired will fail because no class is implementing employeeRepository.

Still, I am confused as to how it works as, every code I saw on GitHub and tutorial, works perfectly.

Where am I going wrong and how does @Autowired work on the interface which extends CrudRepository, even though no class is implementing it; which is the basic rule of Autowiring? That is, if you are auto wiring any interface, at least one class has to implement that interface then and then Autowiring will be successful.

解决方案

Well, there is indeed already a great answer about Spring Data Repositories described in : How are Spring Data repositories actually implemented? . However, when reading your question I believe there is a bit of confusion with regards the way the @Autowired works. Let me try to give the high level sequence of the events :

  1. You place the dependency on the EmployeeRepository in your code :

    
    @Autowired 
    private EmployeeRepository employeeRepository;
    

  2. By doing step (1) you indicate to the Spring container that during its startup process it should find an instance of the class which implements EmployeeRepository and inject it into the target of the @Autowired annotation. I would like here to stress the fact that in order for the injection to work properly you should have the instance of the class implementing the required interface in the Spring container during the runtime and not during the compilation process.

  3. So now a logical questions comes in : "Where from a class implementing the UserRepository appears in the Spring container during its startup process if we have not explicitly defined that class" ?

  4. Thats were a detailed answer from Oliver comes in : How are Spring Data repositories actually implemented?. In the nutshell what happens is that Spring Data during the container bootstrap process scans for the all repositories interfaces; creates new classes (Proxies) which implement these interfaces; puts instances of those classes into the Spring container which allows for @Autowired to find and inject them as it would do for any other Spring bean within the container.

And again, these process works only if you have Spring Data set up and correctly configured, otherwise indeed the injection would fail.

Hope this helps.

这篇关于扩展 CrudRepository 的 @Autowired 接口如何工作?我想有一些见解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆