Tengo una aplicación web ejecutándose con una impl predeterminada de un servicio de back-end. Uno debería ser capaz de implementar la interfaz y soltar el jar en la carpeta de complementos (que no está en la ruta de clase de las aplicaciones). Una vez que se reinicia el servidor, la idea es cargar el nuevo jar en el cargador de clases y hacer que participe en la inyección de dependencias. Estoy usando Spring DI usando @Autowired. La nueva impl del servicio de complemento tendrá la anotación @Primary. Entonces, dados dos impls de la interfaz, la primaria debería estar cargada.Spring Dependency Injection and Plugin Jar
Tengo el jar cargado en el cargador de clases y puedo invocar el impl manualmente. Pero no he podido llegar a participar en Dependency Injection, y he sustituido la impl predeterminada.
Aquí está un ejemplo simplificado:
@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()");
}
}
// Por falta de un lugar mejor, he cargado el frasco plugin de la ContextListener
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>
incluso después de haber cargado el frasco en el cargador de clases, DefaultService todavía se está inyectando como servicio. ¿Alguna idea de cómo obtengo el plugin jar para participar en el ciclo de vida DI de la primavera?
Editado: Para decirlo simplemente, tengo un archivo de guerra que tiene algunos plugins en un directorio de complementos dentro de la guerra. En función de un valor de un archivo de configuración que la aplicación revisa, cuando se inicia la aplicación, quiero cargar ese archivo de complemento particular y ejecutar la aplicación con él. De esa forma, puedo distribuir la guerra a cualquier persona, y ellos pueden elegir qué plugin ejecutar en función de un valor de configuración sin tener que volver a empaquetar todo. Este es el problema que intento resolver.
Gracias. Parece que eso funcionará. Pero estoy usando anotaciones de primavera en gran medida, y no tengo ningún xml de primavera en los archivos jar de complementos. Me pregunto qué tan fácil será hacer lo mismo que arriba para la inyección de dependencia guiada por anotación. – Langali
Debe tener algún tipo de configuración en cada uno de sus complementos (@ver mi respuesta extendida). Incluso si solo se trata de un pequeño archivo XML con solo un ' 'del paquete del complemento, debería estar ** en el complemento ** y en ningún otro lugar. Es el complemento que mejor se conoce y sabe cómo configurarse. El módulo central no debería estar al tanto de la existencia de complementos, solo debería brindarles la posibilidad de unir sus propias configuraciones a 'ApplicationContext'. –
Roadrunner