My first idea was to use Spring component-scan to find my annotated interfaces, and to proxy it via a BeanPostProcessor or something similar, but it cannot works because component-scan can only be used to load implementations and BeanPostProcessor as well.
As I'm using a custom namespace, so a parser, I made some research through Spring namespace elements and I found the attribute: base-package. And one of its associated class: ClassPathScanningCandidateComponentProvider. By extending this class, my annotated interfaces can be found, and the parser will be in charge to create the proxy around these interfaces.
The scanner implementation is quiet simple:
static class MyAnnotComponentProvider extends ClassPathScanningCandidateComponentProvider { public MyAnnotComponentProvider() { super(false); addIncludeFilter(new AnnotationTypeFilter(MyAnnot.class, false)); } @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return beanDefinition.getMetadata().isInterface(); } }
- The constructor defines a scanner without any filter by calling the super constructor with false
- Add a filter on the annotation to found in the classpath by using AnnotationTypeFilter. The second argument specifies only the search must include meta annotation or not.
- Based on the BeanDefinition, isCandidateComponent must must check if the found bean is elligible
Next, use it as follow:
ClassPathScanningCandidateComponentProvider componentProvider = new MyAnnotComponentProvider(); componentProvider.setResourceLoader(parserContext.getReaderContext().getResourceLoader()); final String basePackage = element.getAttribute("base-package"); Set < BeanDefinition > beans = componentProvider.findCandidateComponents(basePackage);
- Instanciate the scanner, and give it a ResourceLoader. In a Spring XML parser, it can be reached by ParserContext
- Get the package to parse by, for example, get the value of the base-package attribute
- Call the method findCandidateComponents to get a Set of BeanDefinition.