Spring:如何在主Bean创建后初始化相关的延迟加载Bean

5

我有一些懒加载的bean的代码:

@Component @Lazy
class Resource {...}

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

初始化应用程序上下文后,这些bean实例不会存在。当应用程序上下文创建bean资源(例如,applicationContext.getBean(Resource.class))时,没有任何标有@CustomProcessor的bean实例。
需要在创建资源bean时使用@CustomProcessor创建bean。如何做到这一点?
更新: 发现了一个丑陋的解决方案——使用空的自动���配setter:
@Autowired
public void setProcessors(List<ResourceProcessor> processor){}

另一种不太优美的解决方案是使用BeanPostProcessor(真神奇!)
@Component
class CustomProcessor implements BeanPostProcessor{
    public postProcessBeforeInitialization(Object bean, String beanName) {
        if(bean instanceof Resource){
            applicationContext.getBeansWithAnnotation(CustomProcessor.class);
        }
    }
}

也许有更优雅的方式?

如果存在并设置为true,则@Lazy的Java文档中指出,@Bean或@Component将不会在被另一个bean引用或从封闭的BeanFactory中明确检索之前初始化。我认为你应该从处理器中删除@Lazy或在Resource bean内放置一个引用。 - Xstian
不,它不起作用是因为ResourceProcessor不是Resource的依赖项。当所有组件都不是惰性加载时,它当然可以正常工作,但我需要使用惰性初始化来完成它。 - mitallast
你可以在Resource中添加@PostConstruct来初始化所有的Processor - Xstian
1
如果您需要在启动时实例化Bean,则不应将其标记为@Lazy。 - DwB
我在思考 Resource 应该实现 ApplicationContextAware,并且在它的 @PostConstruct 方法中,你可以使用 applicationContext.getBeansOfType(ResourceProcessor.class)。是一个有些曲折的想法,但我认为这样做很好:) - Xstian
显示剩余2条评论
1个回答

3

您需要创建一个像 CustomProcessor 这样的标记接口。

public interface CustomProcessor{

}

稍后每个ResourceProcessor都必须实现上述接口。
@Component @Lazy 
class ResourceProcessorFoo implements CustomProcessor{
    @Autowired
    public ResourceProcessor(Resource resource) {...}
}
@Component @Lazy 
class ResourceProcessorBar implements CustomProcessor{
    @Autowired
    public ResourceProcessor(Resource resource) {...}
}

资源必须实现 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;   
    }

}

当引用Resource bean时,将开始执行postconstruct,初始化所有实现CustomProcessor接口的bean。


不幸的是,这是一个难以跨越Spring Framework供应商限制的问题。 此外,最好在没有ApplicationContextAware的情况下使用@Autowired来获取ApplicationContext - mitallast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接