【问题标题】:How to Autowire an interface or abstract class without implementation in Spring如何在 Spring 中自动装配没有实现的接口或抽象类
【发布时间】:2019-02-22 20:37:21
【问题描述】:

我需要自动装配一个没有实现的接口,就像 @Repository 标记功能。

@QueryRepository
public interface EddressBookDao {

    @ReportQuery
    public List<EddressBookDto> loadEddresses(@EqFilter("id") Long id);

}

@Autowired
private EddressBookDao eddressBookDao;

Result result = eddressBookDao.loadEddresses(1L);

我正在考虑在 ClassPathScan 期间以某种方式检测我的 @QueryRepository 注释并在 eddressBookDao Autowire 上注入 EddressBookDao 对象的代理。

现在我正在使用以下方法以繁琐的方式实现此功能:

@Autowired
public ReportQueryInvocationHandler reportQuery;

private EddressBookDao eddressBookDao;

public EddressBookDao eddressBook(){
    if (eddressBookDao == null) eddressBookDao = reportQuery.handle(EddressBookDao.class);
    return eddressBookDao;
}

这是我创建代理的处理程序:

@Component
public class ReportQueryInvocationHandler implements InvocationHandler {
public <T> T handle(Class<T> clazz){
    return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, this);
}

public Object invoke(Object proxy, Method method, Object[] args) throws NoSuchFieldException, IllegalAccessException {

    Type returnType = method.getReturnType();

    Annotation[][] annotations = method.getParameterAnnotations();
    Report report = dao.createReport();

    for (int i = 0; i < args.length; i++) {
        Object argument = args[i];
        Annotation[] annotationList = annotations[i];
        if (annotationList.length == 0) continue;

        for (Annotation annotation : annotationList) {
            Class<? extends Annotation> annotationType = annotation.annotationType();
            String path = null;

            if (annotationType.equals(EqFilter.class)) {
                path = ((EqFilter) annotation).value();
                report.equalsFilter(path, argument);
                break;
            } 
        }
    } 
    return report.list((Class<?>) returnType);
}

我是这样称呼它的:

List<EddressBookDto> addressed = dao.eddressBook().loadEddresses(8305L);

我只想避免编写这段代码

private EddressBookDao eddressBookDao;
public EddressBookDao eddressBook(){
    if (eddressBookDao == null) eddressBookDao = reportQuery.handle(EddressBookDao.class);
    return eddressBookDao;
}

改为这样写:

@Autowired
private EddressBookDao eddressBookDao;

【问题讨论】:

  • 基本上我有自己的 Hibernate 实现,我根据 ReturnType EddressBookDto 和 Param 中的过滤器动态构建自己的 Criteria。我想我应该使用与 @Repository 相同的逻辑并使用 AOP 拦截方法来创建查询并返回结果。

标签: spring hibernate spring-boot spring-data-jpa spring-data


【解决方案1】:

Spring Data 不会自动装配接口,尽管它看起来可能是这样的。它注册了生产代理实现接口的工厂。

要执行类似的操作,您必须实现FactoryBean 接口。 见the JavaDoc for details。还有tutorials available

【讨论】:

  • 感谢提供链接,但我认为我的场景比提供的链接中的FactoryBean更复杂。我必须以某种方式创建我自己的接口注释并让 ClassPathScanner 将其拾取...
  • 看看@EnableJpaRepository注解和它本身的注解。
  • 请检查我更新的代码,我可以为接口创建代理,现在我只需要使用 ClassPathScanning 创建它并自动装配它...
猜你喜欢
  • 2019-05-19
  • 1970-01-01
  • 2020-11-15
  • 2014-06-30
  • 1970-01-01
  • 2019-03-03
  • 2020-10-20
  • 1970-01-01
  • 2019-01-16
相关资源
最近更新 更多