我有一个(web)应用程序需要基于客户使用该应用程序的特殊配置和/或扩展。我将这些添加内容称为#34;插件"并且在应用程序启动时通过类路径扫描自动发现它们。对于非常容易的扩展。让我们说我想要一个插件添加一个API来打印" hello world"当调用URL / myplugin / greet时:我只是使用相应的@Controller
创建一个@RequestMapping
带注释的类,将其放在myplugin.jar
中,将其复制到类路径中,然后将其复制到@Configuration
public class CoreConfiguration {
@Bean
public Set<String> availableModules() {
return Collections.singleton("core");
}
}
。是的。
当我想要更改某些默认值时会出现问题,特别是如果我想多次执行此操作。让我们说我的核心应用程序有这样的配置:
@Configuration
public class FirstPluginConfiguration {
@Bean
public Set<String> availableModules(Set<String> availableModules) {
Set<String> extendedSet = new HashSet<>(availableModules);
extendedSet.add("FirstPlugin");
return extendedSet;
}
}
现在我有两个彼此不了解的插件(但他们确实知道CoreConfig),但他们都希望将自己添加到可用模块列表中。我该怎么办?如果我只有一个想要覆盖模块列表的插件,我可以从CoreConfiguration覆盖现有的bean,但是有两个插件会成为问题。我想象的内容是这样的:
SecondPluginConfiguration
当然CrashLogger
看起来几乎就是这样,除了Set不是由&#34; FirstPlugin&#34;扩展,而是由#34; SecondPlugin&#34;。我测试了它以检查会发生什么,而spring将永远不会调用First / SecondPluginConfiguration&#34; availableModules&#34;方法但它也没有显示错误。
现在当然在这种情况下,可以通过在CoreConfiguration中使用可变Set然后在其他配置中自动装配和扩展集合来轻松解决这个问题,但是例如我也希望能够将方法拦截器添加到某些bean中。例如,我可能有一个接口logCrash(Throwable t)
,它有一个ToFileCrashLogger
方法,在CoreConfiguration中创建了一个org.springframework.aop.framework.Advised
,它将堆栈跟踪写入文件,顾名思义。现在一个插件可以说他也希望得到有关崩溃的通知,例如插件想要通过电子邮件添加到某人的堆栈跟踪。就此而言,插件可以包装由CoreConfiguration配置的CrashLogger并激活BOTH。第二个插件可以再次包装包装器并执行与堆栈跟踪完全不同的操作,并且仍然可以调用其他两个CrashLogger。
后者听起来有点像AOP,如果我只是让我的所有bean都被代理(我没有测试过),我可以将它们自动装入我的插件配置,将它们转换为<button data-url="@Url.Action("MyApi", "Get")"></button>
然后添加操纵行为的建议。然而,为我的每个bean和每个bean生成代理似乎是一个巨大的过度杀伤,只是为了使该插件可以添加一个或两个建议一个或两个bean。