Search code examples
javasingletonspring-iocspring-java-config

What is the best way to implement a component scoped singleton?


Let's say there is an application that creates an instance of the Task class every time when it needs to process some data. The task instance have some other services injected into it but all this services and the task object itself are unique within a single task instance. Some global services are being injected too of course but they are true application wide singletons. So my question is what is the best way to configure injection of that local (or scoped) singleton instances? I am primarily thinking about using a child context but how to configure it properly is still a question to me. One more thing to mention is that I use annotations and java based configuration.


Solution

  • The solution I finally came up with requires to create a child context. The key point is to specify different child configuration so that parent context is unaware about child component dependencies. The simplest solution is to create a separate java config with enabled component scanning and to place it into a dedicated package.

    @Configuration
    @ComponentScan
    public class TaskConfig {}
    
    public interface TaskFactory {
        Task createTask();  
    }
    
    @Component
    public class TaskFactoryImpl implements TaskFactory {
    
        private ApplicationContext parentContext;
    
        @Autowired
        public void setParentContext(ApplicationContext parentContext) {
            this.parentContext = parentContext;
        }
    
        @Override
        public Task createTask() {
            try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
                context.register(TaskConfig.class);
                context.setParent(parentContext);
                context.refresh();
                return context.getBean(Task.class);
            }
        }
    }