最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解如何給Sprintboot應(yīng)用添加插件機(jī)制

 更新時(shí)間:2023年08月25日 09:19:51   作者:陳sir的知識(shí)庫(kù)  
這篇文章主要為大家介紹了如何給 Sprintboot 應(yīng)用添加插件機(jī)制,文中有詳細(xì)的解決方案及示例代碼,具有一定的參考價(jià)值,需要的朋友可以參考下

場(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)文章

最新評(píng)論

汨罗市| 通城县| 繁昌县| 儋州市| 双鸭山市| 河北省| 莱芜市| 福鼎市| 栾川县| 平阳县| 宜兰市| 东莞市| 光山县| 海淀区| 建湖县| 米泉市| 永修县| 桑植县| 九龙坡区| 万安县| 潼南县| 郑州市| 新竹县| 平泉县| 遵化市| 剑川县| 峨山| 当涂县| 台安县| 兰州市| 乌审旗| 乌什县| 巨野县| 兴安盟| 永济市| 黑山县| 达州市| 合川市| 澜沧| 武汉市| 新密市|