5

I have code with lazy initialized beans:

@Component @Lazy
class Resource {...}

@Component @Lazy @CustomProcessor
class ResourceProcessorFoo{
    @Autowired
    public ResourceProcessor(Resource resource) {...}
}
@Component @Lazy @CustomProcessor
class ResourceProcessorBar{
    @Autowired
    public ResourceProcessor(Resource resource) {...}
}

After initialize application context, there's no instances of this beans. When bean Resource is created by application context (as example, applicationContext.getBean(Resource.class)), no instances of @CustomProcessor marked beans.

It's need to create beans with @CustomProcessor when created Resource bean. How to do it?

Updated: One of ugly solution found - use empty autowired setter:

@Autowired
public void setProcessors(List<ResourceProcessor> processor){}

Another ugly solution with bean BeanPostProcessor (so magic!)

@Component
class CustomProcessor implements BeanPostProcessor{
    public postProcessBeforeInitialization(Object bean, String beanName) {
        if(bean instanceof Resource){
            applicationContext.getBeansWithAnnotation(CustomProcessor.class);
        }
    }
}

Maybe there's a more elegant way?

7
  • Form java docs of @Lazy If present and set to true, the @Bean or @Component will not be initialized until referenced by another bean or explicitly retrieved from the enclosing BeanFactory. I think that you should remove @Lazy from processor or put a reference inside Resource bean. Commented Nov 6, 2014 at 13:54
  • No, it's does not work because ResourceProcessor is not a dependency for Resource. When all components is not lazy, of course, it's works correctly, but I need do it with lazy initialization Commented Nov 6, 2014 at 14:41
  • You could add a @PostConstruct within Resource to initialize all Processor. Commented Nov 6, 2014 at 14:55
  • 1
    If you need to instantiate a bean at startup, then you should not mark it as @Lazy Commented Nov 6, 2014 at 15:08
  • @DwB If ResourceProcessor not marked Lazy, it's means that resource not Lazy too. But I need lazy behavior for all this components. Commented Nov 6, 2014 at 20:27

1 Answer 1

3

You must create a marker interface like CustomProcessor

public interface CustomProcessor{

}

later each ResourceProcessor must be implements above interface

@Component @Lazy 
class ResourceProcessorFoo implements CustomProcessor{
    @Autowired
    public ResourceProcessor(Resource resource) {...}
}
@Component @Lazy 
class ResourceProcessorBar implements CustomProcessor{
    @Autowired
    public ResourceProcessor(Resource resource) {...}
}

Resource must implements ApplicationContextAware

@Component
@Lazy
public class Resource implements ApplicationContextAware{

    private ApplicationContext applicationContext;

    @PostConstruct
    public void post(){
        applicationContext.getBeansOfType(CustomProcessor.class);
    }

    public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {
        this.applicationContext = applicationContext;   
    }

}

When Resource bean will be referenced starts the postconstruct that initialize all bean that implements CustomProcessor interface.

Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunately, it's a hard Spring Framework vendor lock. Also, it's better to use @Autowired for ApplicationContext without ApplicationContextAware

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.