@Autowired如何知道JPA Repository该怎样实现?
我是一个JAVA初学者
在看到JPA基础的时候,对于继承JpaRepository
接口后,直接使用@Autowird
即可自动获取相关查询方法感到很神奇,如下:
定义一个repository
接口,继承JpaRepository
@Repositorypublic interface UserRepository extends JpaRepository<User, Long> {
}
直接可以使用:
@SpringBootTest@RunWith(SpringRunner.class)
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
private Long id;
@Before
public void setUp() {
assertNotNull(userRepository);
User user = new User("SnailClimb", 23);
User savedUser = userRepository.saveAndFlush(user);// 更新 user 对象的姓名
savedUser.setName("UpdatedName");
userRepository.save(savedUser);
id = savedUser.getId();
}
我并没有给容器中注入相关Bean,@Autowired是如何知道该怎样正确实现这些方法的?
增加问题描述:
感谢大家的回答,但可能我没有很清晰的描述好我的问题:
其实我想知道的是Spring是如何通过 Repository
接口类型(在UserRepository接口类型上注明了@Autowired),来知道如何注入,注入哪一个实现类的。
比如:
按照Spring自己的用法,我在一个类上注明一个@Component
,就表明这是个Bean
,那么Spring可以很容易的通过反射找到这个类实例化并注册到IoC
容器中,然后在使用的地方注入这个对象即可。
但是我在一个接口上注明@Component
,系统就不应该知道这个接口的方法如何实现。应该是先绑定一个接口到一个已经实现接口的类(我没有找到这一步,所以不太理解注入机制),然后系统去实例化这个接口实现类。但是我不是很清楚Repository
接口是如何绑定到具体实现的。
不知是否表达清楚,大概是这个意思。
回答:
你问的其实是Spring IOC容器的原理
- springboot启动的时候会默认扫码启动类当前目录和子目录下,带有@Component注解的类(包括@Controller、@RestController、@Service等等都是)
- 把扫描到的组件类实例化以后放入容器中,就是bean
- 在依赖某个bean的类实例化时,把带有@Autowired注解的属性、构造方法、setter方法注入bean完成自动装配
另外再说两点
- 你那个@Repository注解其实是不需要的,只要继承了JpaRepository都算repository,因为JpaRepository自带了一个组件注解
- spring4和5版本推荐构造器注入(并且这个方式可以省略@Autowired注解),最核心的优点就是自行实例化具体的类时,不会因为没有注入bean而报错
有一个对应的repository工厂类,根据你repository接口的定义和传入的实体类,自动代理实现了一个基于模板仓库类中的方法+你自定义方法的类的实例放到容器中
相关的两个类,供参考:
https://docs.spring.io/spring...
https://docs.spring.io/spring...
回答:
因为@Repository注解里使用了@Component的
类似的还有@Service、@Controller等
回答:
cglib(或者其他工具)运行期根据注解参数等等生成了具体的类
mybatis的mapper接口同理
以上是 @Autowired如何知道JPA Repository该怎样实现? 的全部内容, 来源链接: utcz.com/p/944422.html