为啥这个 Spring Boot Web 应用不需要 @Repository?
Posted
技术标签:
【中文标题】为啥这个 Spring Boot Web 应用不需要 @Repository?【英文标题】:Why isn't necessary @Repository for this Spring Boot web app?为什么这个 Spring Boot Web 应用不需要 @Repository? 【发布时间】:2019-01-25 20:12:11 【问题描述】:我正在学习 Spring Boot 和 JPA、Spring Data Rest、H2 数据库,并且我找到了一个教程。我试图理解它,这是一个简单的例子,但我不明白。为什么不需要将@Repository
或@Component
放在 AlienRepo 类中?
repo 对象被注入到 AlienController 类中,我从之前的教程中知道你需要使用@Component
或@Repository
。我认为必须使用此注释。
控制器:
package com.dgs.springbootjpa.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.dgs.springbootjpa.dao.AlienRepo;
import com.dgs.springbootjpa.model.Alien;
@Controller
public class AlienController
@Autowired
AlienRepo repo;
@RequestMapping("/")
public String home()
return "home.jsp";
@RequestMapping("/addAlien")
public String addAlien(Alien alien)
repo.save(alien);
return "home.jsp";
POJO:
package com.dgs.springbootjpa.model;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Alien
@Id
private int aid;
private String aname;
public int getAid()
return aid;
public void setAid(int aid)
this.aid = aid;
public String getAname()
return aname;
public void setAname(String aname)
this.aname = aname;
@Override
public String toString()
return "Alien [aid=" + aid + ", aname=" + aname + "]";
dao接口:
package com.dgs.springbootjpa.dao;
import org.springframework.data.repository.CrudRepository;
import com.dgs.springbootjpa.model.Alien;
public interface AlienRepo extends CrudRepository<Alien, Integer>
可以看到AlienRepo界面中没有@Repository
或@Component
,代码运行成功。
谢谢!
更新---------------------------------
我想从数据库中获取数据并添加以下代码。我想问你为什么@RequestParam 不是强制性的?如果我删除了@RequestParam,应用程序就会成功运行。
@RequestMapping("/getAlien")
public ModelAndView addAlien(@RequestParam int aid)
ModelAndView mv = new ModelAndView("showAlien");
Alien alien = repo.findById(aid).orElse(new Alien());
mv.addObject(alien);
return mv;
【问题讨论】:
【参考方案1】:你注意到了吗,CrudRepository 有@NoRepositoryBean 注解,这个注解使CrudRepository 成为一个中间接口。一个中间接口基本上是添加 派生存储库的一般功能。
如果任何使用@NoRepositoryBean
注解的类,Spring Data 不会在运行时创建实例。因为它是中间类,它是为派生类添加功能而创建的。
如果您扩展一个具有@NoRepositoryBean
的接口,而您的派生接口没有@NoRepositoryBean
,Spring 知道您正在尝试在您的真实存储库接口中使用该功能,因此添加@Repository 注释是冗长的。
编辑:为什么@RequestParam 不是强制性的?
从the official documentation可以看到“控制器方法参数”表,表的最后一行写着:
任何其他论点:
如果方法参数与上述任何一个都不匹配,默认情况下它 如果是简单类型,则解析为@RequestParam,如 由BeanUtils#isSimpleProperty 确定,或作为 @ModelAttribute 否则。
因此,如果您省略了“控制器方法参数”的注释,并且您没有编写 @MatrixVariable、@PathVariable 或 @RequestParam 之类的内容。
默认是@RequestParam
。
【讨论】:
非常感谢您的帮助!你能帮我更新一下吗?为什么@RequestParam 不是强制性的? 很高兴为您提供帮助,猫王!我已经更新了我的答案,希望能再次提供帮助。【参考方案2】:@Component
和 @Repository
可以在类上使用,以将它们用作 Spring Bean。但是,AlienRepo
不是一个类,它是一个扩展 Spring Data 接口的接口。 Spring Data 不使用注释,它通过扫描类路径并查看接口层次结构来检测接口,以查看 Spring Data 接口是否被扩展。如果是这种情况,它会在运行时为每个接口创建一个实现,然后将其作为 Spring Bean 添加到应用程序上下文中。这就是为什么您不需要在 Spring Data 接口上进行任何注释。
【讨论】:
【参考方案3】:你的@SpringBootApplication
引入了@EnableAutoConfiguration
注解的效果:
@EnableAutoConfiguration
public @interface SpringBootApplication
此注解将猜测并自动配置 bean。
Spring Data 的 JPA 存储库的自动配置。 当上下文中配置了一个 DataSource 类型的 bean,Spring Data JPA JpaRepository 类型在类路径上,并且没有配置其他现有的 JpaRepository 时激活。
一旦生效,自动配置就相当于使用 EnableJpaRepositories 注解启用 JPA 存储库。
这个配置类会在 Hibernate 自动配置之后激活。
public class JpaRepositoriesAutoConfiguration
当你添加 data-jpa 依赖时,JpaRepositoriesAutoConfiguration
被触发并为你的应用带来@EnableJpaRepositories
注解的效果
Your repository then auto-configured:
Spring Data 存储库通常从 Repository 或 CrudRepository 接口扩展而来。如果您使用自动配置,则从包含您的主配置类(使用 @EnableAutoConfiguration 或 @SpringBootApplication 注释的那个)的包中向下搜索存储库。
【讨论】:
问题是关于@org.springframework.stereotype.Repository
annotation,而不是org.springframework.data.repository.Repository
interface
@Lu55 OP 问题是“为什么不需要将@Repository 或@Component 放在AlienRepo 类中”,我解释了为什么Spring 可以自动完成(自动注册Repository/CrudRepository 子接口通过@EnableJpaRepositories
)。老实说,我什至不知道为什么上面的答案被接受了大声笑【参考方案4】:
您的 AlienRepo
类扩展了 CrudRepository
,因此 Spring 将能够浏览配置中指定的包并找到存储库。
附带说明,如果只有一个构造函数AlienController(AlienRepo)
,您可以删除@Autowired
,Spring 也可以解决这个问题。
【讨论】:
以上是关于为啥这个 Spring Boot Web 应用不需要 @Repository?的主要内容,如果未能解决你的问题,请参考以下文章
为啥必须在 spring-boot 中为 web 应用程序提供单独的 @Controller 类文件?
为啥我的 Spring Boot Web 应用程序无法在 Gradle 中完全运行?