Apache Tapestry:定义要在运行时注入的组件

Apache Tapestry: Define component to be injected at runtime

我有一些组件,应该在运行时可用时注入。基本流程如 this article. 中所述,但是,这篇文章展示了一个非常简单的示例,我想对其进行扩展。

考虑以下因素:
加载网站的索引页面时,如果菜单组件在 class 路径上可用,则会动态添加它们。我能够在运行时找到组件的所有完全限定 class 名称,但无法实例化它们,因为它们应该由 Tapestry IOC Container.

实例化

例如而不是以下

@InjectComponent
private Menu menu;

我想通过代码实例化它。这样,我就可以有一个方法来 return 基于其参数的正确组件:

public Object getMenuComponent(String fullyQualifiedClassName) {
    // Ask the Tapestry IOC Container to retrieve the component based on its classname or library name
    return new Menu();
}

此后我可以通过 .tml 文件中的委托导入组件。

<t:delegate to="getMenuComponent()"/>

new Menu(); 当然是静态占位符,但这当然不起作用,因为从那时起我正在实例化由 IOC container.[=20 管理的 class =]

看了好几篇topic和文章,都说Tapestry是静态结构,不允许。如 the documentation, the Tapestry mailing list or in other mailing lists.

我对 Tapestry 的体验也不是很好,但是有没有其他方法可以解决这个问题?例如注入 IoC container 本身并根据其限定符或 class 名称要求它 return 我的组件?

已找到解决我的问题的方法。 Tapestry 加载 类,因此它们已在容器中可用。我只是不知道如何让他们离开那里。因此,我没有尝试 return 组件,而是解析所有可用页面,加载它们的 类 并检查注释。当我得到我需要的那些时,我 return 他们的页面名称可以在 .tml 中使用。然后在 .tml 文件中,我可以使用现有组件为我加载页面。

控制器中的逻辑如下:

public List<String> getPages() {
    List<String> result = new ArrayList<String>();
    for (final String pageName : this.componentClassResolver.getPageNames()) {
        String className = this.componentClassResolver.resolvePageNameToClassName(pageName);
        Class clazz = loadClass(className);
        if (clazz.isAnnotationPresent(MainPage.class)) {
            result.add(pageName);
        }
    }
    return result;
}

和对应的.tml

<li t:type="loop" source="pages" value="mainPage">
    <t:pagelink page="${mainPage}">${mainPage}</t:pagelink>
</li>