成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

徹底解耦!Spring Boot 實現外部 Jar 動態(tài)加載與熱插拔式擴展架構

開發(fā) 前端
通過動態(tài)構建類加載器、讀取?spring.factories?并手動注冊 Bean,我們成功在 Spring Boot 中實現了外部 Jar 的插件化加載。

在大型系統(tǒng)中,業(yè)務快速變化、功能可插拔、模塊可裁剪成為主流趨勢。為此,我們可以基于 Spring Boot 實現一種插件式架構,支持動態(tài)加載外部 Jar 并熱插拔模塊功能,進一步實現架構解耦、運行期擴展、服務熱更新等目標。

本文將帶你深入實現一套完整的插件機制,加載目錄 /usr/local/java/plugins 中的 Jar 包,并將其中的 Spring Bean 自動注入主工程上下文中。

架構目標與實現思路

核心目標可以拆解為兩個步驟:

  1. 將 Jar 加載到 JVM
  2. 讓 Spring 識別并注冊其中的 Bean

Spring Boot 本身對類加載器有一定擴展能力,再結合自定義加載器和 spring.factories,便可輕松實現這一機制。

項目結構概覽

plugin-loader-demo/
├── plugin-host/                      # 主工程,負責加載插件
│   ├── src/main/java/com/icoderoad/host/
│   │   └── PluginHostApplication.java
│   │   └── loader/
│   │       ├── PluginClassLoader.java
│   │       ├── PluginScanner.java
│   │       └── PluginRegistrar.java
├── plugin-user-center/              # 插件模塊:用戶中心功能
│   ├── src/main/java/com/icoderoad/plugins/user/
│   │   ├── UserService.java
│   │   └── UserAutoConfiguration.java
│   └── resources/META-INF/spring.factories

主工程 plugin-host 的 pom.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.icoderoad</groupId>
  <artifactId>plugin-host</artifactId>
  <version>1.0.0</version>


  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
  </dependencies>


  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <layout>ZIP</layout>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

插件模塊 plugin-user-center 的 pom.xml

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.icoderoad.plugins</groupId>
  <artifactId>plugin-user-center</artifactId>
  <version>1.0.0</version>


  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
  </dependencies>
</project>

插件加載器實現

PluginClassLoader:從目錄中加載外部 Jar

package com.icoderoad.host.loader;


public class PluginClassLoader extends URLClassLoader {
    public PluginClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }


    public static PluginClassLoader fromDirectory(String dirPath) throws IOException {
        File[] jars = new File(dirPath).listFiles(f -> f.getName().endsWith(".jar"));
        if (jars == null) return new PluginClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());


        URL[] urls = Arrays.stream(jars)
            .map(file -> {
                try {
                    return file.toURI().toURL();
                } catch (MalformedURLException e) {
                    throw new RuntimeException(e);
                }
            })
            .toArray(URL[]::new);


        return new PluginClassLoader(urls, Thread.currentThread().getContextClassLoader());
    }
}

PluginScanner:讀取插件 Jar 中的 spring.factories

package com.icoderoad.host.loader;


public class PluginScanner {
    public static List<Class<?>> scanAutoConfigClasses(ClassLoader pluginClassLoader) throws IOException, ClassNotFoundException {
        List<Class<?>> result = new ArrayList<>();
        Enumeration<URL> resources = pluginClassLoader.getResources("META-INF/spring.factories");


        while (resources.hasMoreElements()) {
            try (InputStream input = resources.nextElement().openStream()) {
                Properties props = new Properties();
                props.load(input);
                String classList = props.getProperty(EnableAutoConfiguration.class.getName());
                if (classList != null) {
                    for (String className : classList.split(",")) {
                        result.add(Class.forName(className.trim(), true, pluginClassLoader));
                    }
                }
            }
        }
        return result;
    }
}

PluginRegistrar:注冊配置類到 Spring 容器

package com.icoderoad.host.loader;


public class PluginRegistrar {
    public static void registerPlugins(ConfigurableApplicationContext context, String pluginDir) throws Exception {
        PluginClassLoader loader = PluginClassLoader.fromDirectory(pluginDir);
        List<Class<?>> configClasses = PluginScanner.scanAutoConfigClasses(loader);


        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) context.getBeanFactory();
        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
        reader.setBeanClassLoader(loader);


        for (Class<?> clazz : configClasses) {
            reader.register(clazz);
        }
    }
}

主程序入口整合插件加載邏輯

package com.icoderoad.host;


@SpringBootApplication
public class PluginHostApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(PluginHostApplication.class, args);
        try {
            PluginRegistrar.registerPlugins(context, "/usr/local/java/plugins");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

插件模塊:UserService + 自動配置類

// com.icoderoad.plugins.user.UserService
public class UserService {
    public String getUsername() {
        return "Plugin User";
    }
}


// com.icoderoad.plugins.user.UserAutoConfiguration
@Configuration
public class UserAutoConfiguration {
    @Bean
    public UserService userService() {
        return new UserService();
    }
}

插件 spring.factories 配置

路徑:src/main/resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.icoderoad.plugins.user.UserAutoConfiguration

插件測試驗證代碼

在主應用中通過注入判斷插件是否成功加載:

@Autowired(required = false)
private UserService userService;


@PostConstruct
public void init() {
    if (userService != null) {
        System.out.println("插件加載成功:" + userService.getUsername());
    } else {
        System.out.println("插件未加載!");
    }
}

總結

通過動態(tài)構建類加載器、讀取 spring.factories 并手動注冊 Bean,我們成功在 Spring Boot 中實現了外部 Jar 的插件化加載。

優(yōu)點:

  • 插件 Jar 可獨立開發(fā)部署
  • 插件可運行期動態(tài)加載
  • 支持 Spring 自動配置機制
責任編輯:武曉燕 來源: 路條編程
相關推薦

2021-10-18 10:36:31

Spring Boot插件Jar

2021-10-18 12:04:22

Spring BootJava開發(fā)

2024-08-09 08:46:00

Springjar 包YAML

2022-07-13 08:36:57

MQ架構設計模式

2025-05-12 04:01:00

2021-07-30 13:46:59

前端架構插件

2022-09-02 08:23:12

軟件開發(fā)解耦架構

2025-02-11 07:55:45

2025-05-20 07:13:22

Spring異步解耦Event

2020-11-20 15:22:32

架構運維技術

2025-07-04 09:31:56

2018-04-18 08:47:17

Alluxio構建存儲

2009-10-23 08:12:01

LinuxSCSI硬盤熱插拔

2017-12-26 15:52:31

MQ互聯(lián)網耦合

2017-11-15 09:32:27

解耦戰(zhàn)術架構

2024-10-18 08:00:00

SpringBoot框架開發(fā)

2023-11-20 23:02:36

Spring系統(tǒng)

2023-09-28 08:15:05

SpringBean加載

2025-06-06 01:00:00

Spring場景范式

2021-06-02 06:01:31

Java擴展Jar包
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲午夜精品一区二区三区 | 毛片视频免费观看 | 免费99精品国产自在在线 | 中文字幕亚洲视频 | 亚洲成年影院 | 国产一级免费在线观看 | 久久99精品久久久久久 | av网站在线免费观看 | 国产色网 | 天天影视色综合 | 香蕉一区 | 亚洲在线成人 | 日韩一区二区在线视频 | 国产婷婷精品av在线 | .国产精品成人自产拍在线观看6 | 成人免费视频网站在线观看 | 国产午夜精品久久久 | 黑人久久| 国产一区二区三区在线免费 | 青娱乐自拍 | 久久99精品国产自在现线小黄鸭 | 一本一道久久a久久精品综合蜜臀 | www.伊人.com| caoporn地址 | 久久精品一区二区三区四区 | 在线观看av网站永久 | 成人免费一级视频 | 国产午夜高清 | 玖草资源 | 国产成人一区二区 | 一级毛片免费视频 | 久久天天躁狠狠躁夜夜躁2014 | 日韩在线精品强乱中文字幕 | wwwww在线观看| 懂色中文一区二区三区在线视频 | 久久成人一区 | 在线观看国产精品一区二区 | 在线观看深夜视频 | 日韩免费视频一区二区 | 国产成在线观看免费视频 | 免费看啪啪网站 |