Search code examples
javaspringsingletoncomponentsclassloader

Loading Components/Classes into an ArrayList via some component Name Pattern


I have a number of classes of the same type (com.project.abc.abs.Agent) annotated like so;

@Component("WEB.Agent-1"), @Component("WEB.Agent-2"), @Component("WEB.Agent-3")... etc. For now assume that all classes are in the same package (com.project.abc.web.Agent1...).

These classes are all singletons, and I want to load them dynamically into a central 'Agent manager' class. I.e. every time a new agent class is added with the @Component("WEB.Agent-#") annotation it is picked up without having to make changes to the Agent Manager. In the AgentManager class I need some method to load any component that matches the name "WEB.Agent-#" (where # is a number or some unique ID) is this possible using any methods in Spring?

If not I'm assuming that I would need to go about loading all classes from a particular folder/package?


Solution

  • You can do this with ClassPathScanningCandidateComponentProvider and add an exclude filter that gets rid of things that don't match your pattern:

    ClassPathScanningCandidateComponentProvider scanner =
        new ClassPathScanningCandidateComponentProvider();
    
    scanner.addIncludeFilter(new AnnotationTypeFilter(Component.class));
    scanner.addExcludeFilter(new TypeFilter(){
        public boolean match(MetadataReader metadataReader, 
                             MetadataReaderFactory metadataReaderFactory){
            return metadataReader.getAnnotationMetadata()
                     .getAnnotationAttributes(Component.class.getName())
                     .get("value").matches("WEB.Agent-[0-9]+");
        }
    });
    
    for (BeanDefinition bd : scanner.findCandidateComponents("com.project.abc.web.Agent1"))
        System.out.println(bd.getBeanClassName());