[英]Spring generic repository autowiring failure
我有以下架構:
抽象控制器:
public abstract class AbstractController<E> {
private final AbstractService<E> abstractService;
public AbstractController(AbstractService<E> abstractService) {
this.abstractService = abstractService;
}
@PostMapping("blabla")
public List<Something> getList(@RequestBody whatever) {
return abstractService.method(whatever);
}
}
抽象服務:
public abstract class AbstractService<E> {
@Autowired
private SomeConcreteRepository concreteRepository;
private final EntityTypeAwareRepository<E> entityRepository;
@Autowired(required = false)
public AbstractService(EntityTypeAwareRepository<E> entityRepository) {
this.entityRepository = entityRepository;
}
List<Something> method() {
String tableName = extractTableName(this.entityRepository.getEntityClass());
return this.concreteRepository.someJdbcCall(tableName);
}
}
實體A儲存庫:
@Repository
public interface EntityARepository extends EntityTypeAwareRepository<A>, JpaRepository<A, Long>, JdbcRepository {
// JdbcRepository has implementation for A entity and its methods are called with EntityARepository in service layer
}
實體A控制器:
@RestController
@RequestMapping("base/mapping")
public class AController extends AbstractController<A> {
private final AService aService;
@Autowired
public AController(AService aService) {
super(aService);
this.aService = aService;
}
// concrete endpoints methods
}
實體A服務:
@Service
@PreAuthorize(someRole)
@Transactional
public class AService extends AbstractService<A> {
private final ARepository aRepository;
@Autowired
public AService(ARepository aRepository) {
super(aRepository);
this.aRepository = aRepository;
}
//methods using Spring-JPA aRepository methods
//and
//methods using JdbcRepository interface implementation (via same reference)
}
並針對您喜歡的任何實體進行縮放。 EntityTypeAwareRepository
是NoBeanRepository
具有使用defualt方法查找具體存儲庫實體的方法。 要點。 抽象控制器正在從客戶端獲得針對不同種類實體的呼叫,但涉及同一件事。 因此,目標是一個抽象控制器將處理對N個子控制器的調用。 SomeConcreteRepository
是處理此邏輯的具體類。
問題在於,它與抽象服務中的entityRepository
一起無法自動entityRepository
。 造成NPE。 實際上,后者是從子控制器傳遞的,但解析為null。
實際上,在這種配置下,我可以通過某種方式使它工作,但是第二天自動裝配不能正常工作。 因此,我不確定這種體系結構是否存在問題,或者我只是遇到了魔術般可行的建築問題。 您知道什么會引起問題嗎? 它可以與@Transactional的代理連接嗎?
我確信一切都已正確掃描並且所有bean都可見。
在您的抽象控制器中,我將創建一個abstract AbstractService<E> getService()
方法。 然后在具體的控制器中,實現該吸氣劑:
public abstract class AbstractController<E> {
abstract AbstractService<E> getService();
@GetMapping("/{id}")
public E findById(Long id) {
return getService().findById(id);
}
@PostMapping
public E save(E entity) {
return getService().save(entity);
}
}
然后,具體控制器如下所示:
@RestController
@RequestMapping("/a")
public AController extends AbstractController<A> {
@AutoWired
AService service;
public AbstractService<A> getService() {
return service;
}
}
該服務將使用abstract EntityRepository<E> getRepository()
實現相同的模式
public abstract class AbstractService<E> {
public abstract EntityRepository<E> getRepository();
public E findById(Long id) {
return getRepository().findById(id);
}
public E save(E entity) {
return getRepository().save(entity);
}
}
具體服務如下所示:
@Service
public class AService extends AbstractService<A> {
@Autowired
ARepository repository;
public EntityRepository<A> getRepository() {
return repository;
}
}
存儲庫是最后一層。 “抽象的”存儲庫如下所示:
@NoBeanRepository
public interface EntityRepository<E> extends EntityTypeAwareRepository<E>, JpaRepository<E, Long>, JdbcRepository {
// Implementations are inherited... for findById(Long id), save(E entity), etc
}
然后,我們使用“具體的”存儲庫對此進行擴展:
@Repository
public interface ARepository extends EntityRepository<A> {
}
我們得到如下內容:
這樣,我們在“抽象”層就沒有服務或存儲庫的實例變量。 我們只能通過抽象獲取器訪問具體版本。 服務和存儲庫的具體實現是分別自動裝配特定存儲庫和服務的實現的類。
我對此的原始答案在這里
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.