我的自定义存储库实现中的CrudRepository
我试图获得对我的存储库接口( UserRepository
)的引用,该接口在我的自定义实现( UserRepositoryExtensionImpl
)中扩展CrudRepository
,以便获得对Spring JPA提供的所有方法的访问。
Crud扩展:
@Repository public interface UserRepository extends CrudRepository, UserRepositoryExtension { ...any custom spring JPA methods... }
扩展接口:
@Repository public interface UserRepositoryExtension { public T put(T entity); }
定制实施:
public class UserRepositoryExtensionImpl implements UserRepositoryExtension { UserRepository userRepository; @Autowired public UserRepositoryExtensionImpl(UserRepository userRepository) { this.userRepository = userRepository; } @Override public User put(User user) { System.out.println(user + "was put"); // ...put logic here return null; }... }
但是,我无法注入UserRepository
因为存在循环依赖(假设UserRepository
扩展了我的UserRepositoryImpl
实现的接口)。 我收到以下错误:
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ' userRepositoryImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?
一个可能但不太理想的解决方案是将EntityManager
注入UserRepositoryImp
,但在这种情况下,我无法访问CrudRepository
提供的任何Spring JPA方法,或者我可能在UserRepository中创建的任何其他方法。
关于如何解决这个问题的任何建议?
任何帮助将不胜感激。
编辑:正如在@ Shelley的回答中提到的,我能够通过进行3次更改来解决这个问题:
- 从
UserRepositoryExtensionImpl
删除UserRepositoryExtensionImpl
- 将
UserRepositoryExtensionImpl
重命名为UserRepositoryImpl
。 显然,这使得Spring意识到实现的存在。 见Spring Doc - 删除我的构造函数并将
@Autowired
移动到userRepository
字段
成功!
为了实现这一点,需要更改几件小事:
-
从自定义存储库接口(
UserRepositoryExtension
)中删除UserRepositoryExtension
。 -
自定义存储库实现实际上应该命名为“
”而不是“Impl
”。 在您的代码示例中,这应该是Impl UserRepositoryImpl
而不是UserRepositoryExtensionImpl
。
正如Shelley指出的那样,命名对于使autowire工作非常重要。 在下面的示例中,我遵循自定义界面及其实现的正确命名标准。 但我扩展JpaRepository的界面被命名为“ItemDao”而不是“ItemRepository”,这导致Spring完全忽略了我的自定义实现……
OBS! 应该是“ItemRepository”
@Repository public interface ItemDao extends JpaRepository- , ItemRepositoryCustom {}
我的界面
interface ItemRepositoryCustom {...}
我的实现类
class ItemRepositoryImpl implements ItemRepositoryCustom {...}
如果有人遇到类似问题,请首先遵循以下链接中弹簧文档中使用的命名标准。
有一种明确定义的方法可以在Spring Data JPA中创建自定义存储库实现 ,您应该遵循这些方法。 基本上你需要扩展CrudRepository
这样你就不必在自定义实现中注入它的实例。
我通过使用applicationContext.getBean(UserRepository.class)
注入ApplicationContext
并以懒惰方式获取bean来解决问题。 它以这种方式工作。
我找到了如何在不需要@Autowire
情况下做到这一点:
public interface UserRepository extends UserRepositoryBasic, UserRepositoryExtension { } public interface UserRepositoryBasic extends JpaRepository { // standard Spring Data methods, like findByLogin } public interface UserRepositoryExtension { public void customMethod(); } public class UserRepositoryExtensionImpl implements UserRepositoryExtension { private final UserRepositoryBasic userRepositoryBasic; // constructor-based injection public UserRepositoryExtensionImpl( UserRepositoryBasic userRepositoryBasic) { this.userRepositoryBasic = userRepositoryBasic; } public void customMethod() { // we can call all basic Spring Data methods using // userRepositoryBasic } }