詳解如何給Sprintboot應(yīng)用添加插件機(jī)制
場(chǎng)景
想要讓boot應(yīng)用增加插件能力,擴(kuò)展restful api。插件可以由第三方開(kāi)發(fā)
要解決的問(wèn)題
- 第三方的api需要和主應(yīng)用使用相同的pom依賴(lài)
- 第三方的api獨(dú)立打包成jar包,并按照命名規(guī)則取名
- 第三方的api需要再boot應(yīng)用之外的獨(dú)立存儲(chǔ)中放置(部署)
- 第三方的api jar 包的加載時(shí)機(jī)及方式
方案
- 獨(dú)立的依賴(lài)管理 pom 第三方插件繼承此pom 統(tǒng)一依賴(lài)
- api jar 包放置到特定路徑。由boot 啟動(dòng)時(shí)加載。(也可以熱加載,但實(shí)現(xiàn)方式復(fù)雜一些)
- 技術(shù)點(diǎn) classloader 加載插件 jar, 類(lèi)型需要添加到spring bean 中統(tǒng)一管理生命周期。
下面是classloader的實(shí)現(xiàn)
public class ClassLoaderUtil {
public static ClassLoader getClassLoader(String url) {
try {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
if (!method.isAccessible()) {
method.setAccessible(true);
}
URLClassLoader classLoader = new URLClassLoader(new URL[]{}, ClassLoader.getSystemClassLoader());
method.invoke(classLoader, new URL(url));
return classLoader;
} catch (Exception e) {
log.error("getClassLoader-error", e);
return null;
}
}
}啟動(dòng)時(shí)將類(lèi)加入到spring中
public class PluginImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
private final String targetUrl = "file:/D:/SpringBootPluginTest/plugins/plugin-impl-0.0.1-SNAPSHOT.jar";
private final String pluginClass = "com.plugin.impl.PluginImpl";
@SneakyThrows
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
ClassLoader classLoader = ClassLoaderUtil.getClassLoader(targetUrl);
Class<?> clazz = classLoader.loadClass(pluginClass);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
BeanDefinition beanDefinition = builder.getBeanDefinition();
registry.registerBeanDefinition(clazz.getName(), beanDefinition);
}
}運(yùn)行時(shí)將類(lèi)加載到spring中,此時(shí)需要用ApplicationContextAware
@Component
public class SpringUtil implements ApplicationContextAware {
private DefaultListableBeanFactory defaultListableBeanFactory;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
this.defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
}
public void registerBean(String beanName, Class<?> clazz) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition());
}
public Object getBean(String name) {
return applicationContext.getBean(name);
}
}做一個(gè)運(yùn)行時(shí)加載的入口
@GetMapping("/reload")
public Object reload() throws ClassNotFoundException {
ClassLoader classLoader = ClassLoaderUtil.getClassLoader(targetUrl);
Class<?> clazz = classLoader.loadClass(pluginClass);
springUtil.registerBean(clazz.getName(), clazz);
PluginInterface plugin = (PluginInterface)springUtil.getBean(clazz.getName());
return plugin.sayHello("test reload");到此這篇關(guān)于詳解如何給Sprintboot應(yīng)用添加插件機(jī)制的文章就介紹到這了,更多相關(guān)Sprintboot應(yīng)用添加插件機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot項(xiàng)目里面發(fā)起http請(qǐng)求的幾種方法
Spring Boot發(fā)起HTTP請(qǐng)求有多種方法,包括:RestTemplate,WebClient, HttpClient, Feign Client,第三方庫(kù)如OkHttp和Apache HttpClient,下面就來(lái)詳細(xì)的介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下2025-12-12
idea使用tomcat報(bào)404的問(wèn)題及解決過(guò)程
解決Tomcat部署問(wèn)題:檢查路徑是否正確(JSP文件避免放在WEB-INF)、確保Tomcat配置路徑一致,必要時(shí)重新部署,若日志亂碼,修改logging.properties中編碼為GBK2025-08-08
Java中的靜態(tài)內(nèi)部類(lèi)詳解及代碼示例
這篇文章主要介紹了Java中的靜態(tài)內(nèi)部類(lèi)詳解及代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
Java實(shí)現(xiàn)獲取前、后N天日期的函數(shù)分享
本文給大家分享的是使用java實(shí)現(xiàn)的獲取當(dāng)前日期前后N天的函數(shù),非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2015-03-03
Java使用OpenCV3.2實(shí)現(xiàn)視頻讀取與播放
這篇文章主要為大家詳細(xì)介紹了Java使用OpenCV3.2實(shí)現(xiàn)視頻讀取與播放,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
使用Spring Boot框架整合Redis的超詳細(xì)案例教程
本文詳細(xì)介紹了如何在SpringBoot項(xiàng)目中整合Redis,包括依賴(lài)配置、連接設(shè)置、基本操作和應(yīng)用案例,通過(guò)整合,可以充分利用SpringBoot和Redis的優(yōu)勢(shì),提升應(yīng)用性能和可擴(kuò)展性,感興趣的朋友跟隨小編一起看看吧2025-11-11
Java用?Gradle配置compile及implementation和api的區(qū)別
這篇文章主要介紹了Java用Gradle配置compile及implementation和api的區(qū)別,文章圍繞主題的相關(guān)資料展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06

