Reputation: 2155
I need to Autowire an interface without an implementation, somehow like the @Repository tag functionality.
@QueryRepository
public interface EddressBookDao {
@ReportQuery
public List<EddressBookDto> loadEddresses(@EqFilter("id") Long id);
}
@Autowired
private EddressBookDao eddressBookDao;
Result result = eddressBookDao.loadEddresses(1L);
I'm thinking of somehow detecting my @QueryRepository
Annotation during ClassPathScan and injecting a Proxy of EddressBookDao
object on eddressBookDao
Autowire.
Right now I am achieving this functionality in a cumbersome way using the following:
@Autowired
public ReportQueryInvocationHandler reportQuery;
private EddressBookDao eddressBookDao;
public EddressBookDao eddressBook(){
if (eddressBookDao == null) eddressBookDao = reportQuery.handle(EddressBookDao.class);
return eddressBookDao;
}
Here is my Handler creating the Proxy:
@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);
}
And here is how I'm calling my it:
List<EddressBookDto> addressed = dao.eddressBook().loadEddresses(8305L);
All I want is to avoid writing this code
private EddressBookDao eddressBookDao;
public EddressBookDao eddressBook(){
if (eddressBookDao == null) eddressBookDao = reportQuery.handle(EddressBookDao.class);
return eddressBookDao;
}
And write this instead:
@Autowired
private EddressBookDao eddressBookDao;
Upvotes: 1
Views: 1191
Reputation: 81907
Spring Data doesn't autowire interfaces although it might look this way. It registers factories which produce proxies implementing the interface.
To do something similar you have to implement the FactoryBean
interface.
See the JavaDoc for details. There are also tutorials available.
Upvotes: 1