Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring在运行时添加外部Spring上下文_Java_Spring - Fatal编程技术网

Java Spring在运行时添加外部Spring上下文

Java Spring在运行时添加外部Spring上下文,java,spring,Java,Spring,我们有一个包含多个组件(小部件)的主页,有点像一个包含portlet的门户。这些小部件中的一些将由其他团队提供广告jar,其中一些将需要一些定制bean由Spring管理。一种解决方案可能是使用带有I通配符的import语句导入spring上下文(例如,导入classpath匹配上下文小部件-*.xml中的所有上下文) 然而,我更喜欢一个更具编程性的解决方案,其中我检查每个小部件需要加载的上下文(从类路径)。我没有找到任何博客或类似的解释,但确实在论坛上找到一些帖子,解释这将是一个亲子背景,这将

我们有一个包含多个组件(小部件)的主页,有点像一个包含portlet的门户。这些小部件中的一些将由其他团队提供广告jar,其中一些将需要一些定制bean由Spring管理。一种解决方案可能是使用带有I通配符的import语句导入spring上下文(例如,导入classpath匹配上下文小部件-*.xml中的所有上下文)

然而,我更喜欢一个更具编程性的解决方案,其中我检查每个小部件需要加载的上下文(从类路径)。我没有找到任何博客或类似的解释,但确实在论坛上找到一些帖子,解释这将是一个亲子背景,这将只是单向的;不幸的是,在我的情况下,它需要是双向的

因此,在浏览了一些API之后,我设法想出了一些可行的方法,但我不相信这是一个好的解决方案,或者说有任何我没有想到的陷阱。也许有另一个(更好的)解决方案

public class WidgetManager implements ApplicationContextAware
{

    @Autowired
    private WidgetService widgetService;

    @Override
    public void setApplicationContext(ApplicationContext parentApplicationContext) throws BeansException {
        //I do need the parent context to have finished initializing beans
        List<WidgetTO> widgets = widgetService.findAllWidgets();

        List<String> contexts = newArrayListWithCapacity(widgets.size());
        for (WidgetTO widget : widgets) {
            if (isNotBlank(widget.getSpringContext())) {
                contexts.add(widget.getSpringContext());
            }
        }

        AbstractRefreshableWebApplicationContext parentContext = (AbstractRefreshableWebApplicationContext) parentApplicationContext;

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(contexts.toArray(new String[] {}), parentApplicationContext);
        String[] singletonNames = context.getBeanFactory().getSingletonNames();
        for (String s : singletonNames) {
            //copy all singletons that don't already exist from child to parent
            if (!parentContext.getBeanFactory().containsSingleton(s)) {
                parentContext.getBeanFactory().registerSingleton(s, context.getBeanFactory().getSingleton(s));
            }
        }

    }
}
公共类WidgetManager实现ApplicationContextAware
{
@自动连线
私人WidgetService WidgetService;
@凌驾
public void setApplicationContext(ApplicationContext parentApplicationContext)抛出BeansException{
//我确实需要父上下文来完成初始化bean
List widgets=widgetService.findAllWidgets();
List contexts=newArrayListWithCapacity(widgets.size());
for(WidgetTO小部件:小部件){
if(isNotBlank(widget.getSpringContext())){
add(widget.getSpringContext());
}
}
AbstractRefreshableWebApplicationContext parentContext=(AbstractRefreshableWebApplicationContext)parentApplicationContext;
ClassPathXmlApplicationContext上下文=新的ClassPathXmlApplicationContext(contexts.toArray(新字符串[]{}),parentApplicationContext);
字符串[]SingleToNames=context.getBeanFactory().getSingleToNames();
用于(字符串s:单吨名称){
//将所有不存在的单例从子项复制到父项
如果(!parentContext.getBeanFactory().containsSingleton)){
parentContext.getBeanFactory().registerSingleton(s,context.getBeanFactory().getSingleton(s));
}
}
}
}

您可能可以使用AutowireCapableBeanFactory。此类允许您将bean添加到现有的Spring上下文中。它将实例化bean并注入它们的依赖项

我不确定我是否理解你所说的“双向”上下文。您是否需要主上下文bean依赖于“子上下文”/其他上下文中的bean?如果是这样,通配符导入可能是您的最佳选择,即使您不喜欢该解决方案


如果您更详细地解释整个应用程序生命周期,描述“父/主上下文”和“子/其他上下文”的阶段,可能会有所帮助

实际上我就是这样做的。我们使用这种方式已经3年多了,从来没有出现过问题。

您没有提到为什么需要在父上下文中访问这些bean。也许它不必是双向的?它可能会导致冲突和其他不可预测的结果。好的一点是,它实际上是一个wicket应用程序(应该提到这一点)。主页是wicket网页,小部件是wicket面板(通过反射初始化)。创建小部件面板时,Wicket(@SpringBean)将查找bean(在子上下文xml中定义)。我猜wicket会在父上下文中查找这个bean(它是否知道任何子上下文)?至少,当我简单地创建一个引用父上下文的新类PathAppContext时,无法找到bean(除非我在父上下文xml中定义它)。我明白了,不幸的是,我不熟悉wicket,但我会深入研究@SpringBean(SpringComponentInjector?)背后的机制。也许您可以自定义/替换它,并实现扫描所有子上下文的扩展查找。我会认真考虑这样的算法显式查找顺序-如果bean名称重叠?在某种程度上不确定的父上下文作为一个全局空间。在读取和添加子上下文之前,已经需要刷新(初始化)父上下文,因为要知道要添加哪些子上下文,我需要(父)bean(widgetService)可用。2.我想我是通过
如果(!parentContext.getBeanFactory().containsSingleton))
来防止重复的。