Lan*_*ali 13 java plugins spring java-ee
我的Web应用程序运行时带有后端服务的默认impl.一个人应该能够实现接口并将jar放入plugins文件夹(不在apps类路径中).重新启动服务器后,我们的想法是将新jar加载到类加载器中,并让它参与依赖注入.我使用@Autowired使用Spring DI.新的插件服务impl将具有@Primary注释.因此,给定两个接口的impls,应该加载primary.
我将jar加载到类加载器中并可以手动调用impl.但是我无法参与依赖注入,并让它替换默认的impl.
这是一个简化的例子:
@Controller
public class MyController {
@Autowired
Service service;
}
//default.jar
@Service
DefaultService implements Service {
public void print() {
System.out.println("printing DefaultService.print()");
}
}
//plugin.jar not in classpath yet
@Service
@Primary
MyNewService implements Service {
public void print() {
System.out.println("printing MyNewService.print()");
}
}
Run Code Online (Sandbox Code Playgroud)
//由于缺少更好的地方,我从ContextListener加载了插件jar
public class PluginContextLoaderListener extends org.springframework.web.context.ContextLoaderListener {
@Override
protected void customizeContext(ServletContext servletContext,
ConfigurableWebApplicationContext wac) {
System.out.println("Init Plugin");
PluginManager pluginManager = PluginManagerFactory.createPluginManager("plugins");
pluginManager.init();
//Prints the MyNewService.print() method
Service service = (Service) pluginManager.getService("service");
service.print();
}
}
<listener>
<listener-class>com.plugin.PluginContextLoaderListener</listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)
即使我将jar加载到类加载器中,DefaultService仍然作为服务注入.知道如何让插件罐参与弹簧的DI生命周期吗?
编辑:简单地说,我有一个战争文件,在战争中的插件目录中有一些插件罐.基于应用程序查看的配置文件中的值,当应用程序启动时,我想加载该特定的插件jar并使用它运行应用程序.这样,我可以将战争分发给任何人,他们可以根据配置值选择运行哪个插件,而无需重新打包所有内容.这是我试图解决的问题.
看起来你需要的就是ApplicationContext
正确创建Spring .我认为没有 classpath mingling 是可能的.最重要的事情是Spring配置文件的位置内的类路径.所以把你的所有插件jar放入WEB-INF/lib
并继续阅读.
让我们从核心模块开始.我们将创建它ApplicationContext
来自位于的文件classpath*:META-INF/spring/*-corecontext.xml
.
现在我们将使所有插件将其配置文件放在其他位置.即'myplugin1'将具有如下配置位置:classpath*:META-INF/spring/*-myplugin1context.xml
.而anotherplugin
将在CONFIGS classpath*:META-INF/spring/*-anotherplugincontext.xml
.
你看到的是一种对流.如果您愿意,也可以使用子目录:
classpath*:META-INF/spring/core/*.xml
classpath*:META-INF/spring/myplugin1/*.xml
classpath*:META-INF/spring/anotherplugin/*.xml
重要的是,地点必须是不相交的.
剩下的就是将正确的位置传递给ApplicationContext
创作者.对于Web应用程序,正确的地方是扩展ContextLoaderListener
和覆盖方法customizeContext(ServletContext, ConfigurableWebApplicationContext)
.
剩下的就是读取您的配置文件(它的位置可以作为servlet init参数传递).比你需要构建配置位置列表:
String locationPrefix = "classpath*:META-INF/spring/";
String locationSiffix = "/*.xml";
List<String> configLocations = new ArrayList<String>();
configLocations.add(locationPrefix + "core" + locationSiffix);
List<String> pluginsTurnedOn = getPluginsTurnedOnFromConfiguration();
for (String pluginName : pluginsTurnedOn) {
configLocations.add(locationPrefix + pluginName + locationSiffix);
}
applicationContext.setConfigLocations(configLocations.toArray(new String[configLocations.size()]));
Run Code Online (Sandbox Code Playgroud)
这样您就可以轻松管理Spring中加载的内容和内容ApplicationContext
.
更新:
为了让它发挥作用,我做了一个更隐藏的假设,我现在要解释.核心模块和每个插件的基础包也应该是不相交的.那就是:
这样,每个模块都可以<context:componet-scan />
轻松地使用(在JavaConfig中等效)来为它自己的类添加类路径扫描.核心模块不应包含任何插件包的任何包扫描.该插件应扩大配置的ApplicationContext
自己的包到类路径扫描.
归档时间: |
|
查看次数: |
3440 次 |
最近记录: |