Background
Dynamic plug-in programming is a cool thing to achieve decoupling of business functions for easy maintenance, in addition to enhance scalability can be extended at any time without stopping the server, but also has a very good openness in addition to their own R & D staff can develop features, but also to accept third-party developers in accordance with the specifications of the development of plug-ins.
The common implementation of dynamic plug-ins are SPI
, OSGI
and other solutions, which cannot be injected into the main program’s bean objects in the plug-in because they are not managed by Spring IOC.
This article introduces the idea of hot-loading jar packages in Spring Boot projects and registering them as bean objects to dynamically extend the functionality while supporting the injection of the main application’s beans into the plug-in to achieve a more powerful plug-in.
Hotloading jar packages
Dynamically loading a jar package through a specified link or path can be done using the addURL
method of the URLClassLoader
, with the following sample code.
ClassLoaderUtil
|
|
When creating the URLClassLoader
, specify the current system ClassLoader as the parent class loader ClassLoader.getSystemClassLoader()
This step is more critical to open the ClassLoader between the main program and the plug-in, and solve various problems when registering the plug-in into the IOC ClassNotFoundException problems when registering plugins into the IOC.
Dynamic Registration Bean
Register the implementation classes loaded in the plugin jar to Spring’s IOC, and also inject the beans already in the IOC into the plugin; two scenarios of implementation at program startup and runtime, respectively.
Bean registration at startup
Use the ImportBeanDefinitionRegistrar
to dynamically register the plugin’s beans at Spring Boot startup, with the following sample code.
PluginImportBeanDefinitionRegistrar
|
|
Runtime Registration Bean
The bean that dynamically registers the plugin at runtime is implemented by using the ApplicationContext
object, with sample code as follows.
|
|
SpringUtil
|
|
Summary
This article introduces the plug-in implementation idea by shared ClassLoader and dynamically registered bean way to open the class loader and Spring container between the plug-in and the main program, which makes it very convenient to achieve class interaction between the plug-in and the plug-in and between the plug-in and the main program, such as injecting the main program’s Redis and DataSource in the plug-in, calling the remote Dubbo interface and so on.
However, since there is no isolation of the ClassLoader
between plug-ins, there may be problems such as class conflicts and version conflicts; and since the Class object in the ClassLoader cannot be destroyed, there is no way to dynamically modify the classes loaded into the ClassLoader unless the class name or class path is changed.
So this solution is more suitable for the plug-in data volume is not too much, with a better development specification, plug-in after testing before going online or release scenarios.