GithubHelp home page GithubHelp logo

mchgood / exp Goto Github PK

View Code? Open in Web Editor NEW

This project forked from stateis0/exp

0.0 0.0 0.0 1.22 MB

Java extension plugin and hot swap plugin(Java 扩展点/插件系统,支持热插拔,旨在解决大部分软件的功能定制问题)

License: Apache License 2.0

Java 100.00%

exp's Introduction

⭐️⭐️⭐️Introduction

🚕🚕🚕EXP (Extension Plugin) Extension Point Plugin System

⭐️⭐️⭐️⭐️⭐️中文文档⭐️⭐️⭐️⭐️⭐️

⭐️⭐️⭐️⭐️⭐️钉钉开源社区⭐️⭐️⭐️⭐️⭐️

Related Articles 🎯🎯🎯EXP: A Java Plugin Hot-Swapping Framework

Noun Definitions:

🏅 Main Application: EXP needs to run on a JVM, typically as a Spring Boot application, which is referred to as the main application.

🎖 Extension Point: An interface defined by the main application that can be implemented by plugins. It's important to note that plugins are concrete implementations of extension points, while extension points themselves are merely interface definitions. A plugin can contain implementations for multiple extension points, and a single extension point can have implementations from multiple plugins.

🥇 Plugin: Supports extending functionality through a plugin mechanism, similar to plugins in tools like IDEA or Eclipse. The code within a plugin follows a format similar to Spring (if your application operates within a Spring environment).

🥈 Hot Swapping: Plugins have the ability to be removed from the JVM and Spring container. They support dynamic installation of JAR and ZIP files at runtime. This means you can add, remove, or replace plugins while the application is running, enabling dynamic extension and upgrades of the system.

The above describe the terms and definitions related to the EXP (Extension Plugin) Extension Point Plugin System. This system allows you to build applications with dynamic extension capabilities, adding and managing new functional modules through the use of plugins in the main application.

🎧Example

Both Guizhou Maotai and Wuliangye have purchased your company's standard products. However, due to custom requirements from the clients, new features need to be developed.

  • Guizhou Maotai has customized 2 plugins.
  • Wuliangye has customized 3 plugins.
  • During runtime, the program will perform logic switching based on the client's tenant ID.

Scenario:

  • Large B2B customers customize their business processes, requiring extensions to the main codebase.

    • The conventional approach involves pulling branches from Git.
    • The current method employs an extension point-based approach for customization, allowing hot-swapping.
  • Multiple programs need to be divisible and combinable, supporting the deployment of multiple Spring Boot applications as a single unit or separately.

  • Extension points are similar to Swagger documentation, serving as documentation for the plugin system, which is showcased on the management platform.

Feature

  1. Support hot-swapping or loading during startup (Spring or regular JVM).
  2. Based on the classloader Parent First isolation mechanism.
  3. Support multiple implementations for a single extension point in a multi-tenant scenario, with tenant-based filtering for business logic, and customizable sorting for multiple tenant implementations.
  4. Compatible with Spring Boot 3.x/2.x/1.x dependencies.
  5. Enable plugins to expose Spring Controller REST endpoints externally, with hot-swapping capability.
  6. Allow plugins to override Spring main application Controllers.
  7. Provide support for plugins to access exclusive configurations, enabling customizable design for hot-reloading plugin configurations.
  8. Support transaction binding between plugins and the main application.
  9. Offer a stream API to ensure a cleaner integration of extension points into the main application.

USE

Environment:

  1. JDK 1.8
  2. Maven
git clone [email protected]:stateIs0/exp.git
cd all-package
mvn clean package

Main Application Dependencies(springboot starter)

<dependency>
    <groupId>cn.think.in.java</groupId>
    <!-- Here is a Spring Boot 2 example. If it's a regular application or a Spring Boot 1/3 application, please replace the artifactId.  -->
    <artifactId>open-exp-adapter-springboot2-starter</artifactId>
</dependency>

Plugin Dependencies

<dependency>
   <groupId>cn.think.in.java</groupId>
   <artifactId>open-exp-plugin-depend</artifactId>
</dependency>

Using the Programming Interface API

ExpAppContext expAppContext = ExpAppContextSpiFactory.getFirst();

public String run(String tenantId) {
   List<UserService> userServices = expAppContext.get(UserService.class, TenantCallback.DEFAULT);
   // first The first is the tenant with the highest priority.
   Optional<UserService> optional = userServices.stream().findFirst();
   if (optional.isPresent()) {
       optional.get().createUserExt();
   } else {
       return "not found";
   }
}


public String install(String path, String tenantId) throws Throwable {
  Plugin plugin = expAppContext.load(new File(path));
  return plugin.getPluginId();
}

public String unInstall(String pluginId) throws Exception {
  log.info("plugin id {}", pluginId);
  expAppContext.unload(pluginId);
  return "ok";
}

Module

  1. all-package Packaging module
  2. bom-manager pom management, self-management and tripartite dependency management
  3. open-exp-code exp core
  4. example exp Use sample code
  5. spring-adapter springboot starter, exp Adaptive spring boot

module dependency

core API

public interface ExpAppContext {
   /**
    * Gets all current plug-in ids
    */
   List<String> getAllPluginId();
   
   /**
    * Preload reads only the meta information and load boot class and configuration, and does not load beans.
    */
   Plugin preLoad(File file);
   
   /**
    * loading plugin
    */
   Plugin load(File file) throws Throwable;

   /**
    * Uninstall plugin
    */
   void unload(String pluginId) throws Exception;

   /**
    * Gets plug-in instances for multiple extension points
    */
   <P> List<P> get(String extCode);


   /**
    * To simplify the operation, code is the full path class name
    */
   <P> List<P> get(Class<P> pClass);


   /**
    * Gets a single plug-in instance.
    */
   <P> Optional<P> get(String extCode, String pluginId);
}

Streaming API

public interface StreamAppContext {

   /**
    * For apis with return values, you need to support streaming calls
    */
   <R, P> R streamList(Class<P> pClass, Ec<R, List<P>> ecs);

   /**
    * For apis with return values, you need to support streaming calls
    */
   <R, P> R stream(Class<P> clazz, String pluginId, Ec<R, P> ec);
}

extension

cn.think.in.java.open.exp.client.PluginFilter

/**
 * @Author cxs
 **/
public interface PluginFilterService {

   <P> List<P> get(String extCode, PluginFilter filter);

   <P> List<P> get(Class<P> pClass, PluginFilter callback);
}

Tenant filtering example code:

PluginFilter filter = new PluginFilter() {
   @Override
   public <T> List<FModel<T>> filter(List<FModel<T>> list) {
      return list;
   }
}
;
List<UserService> userServices = expAppContext.get(UserService.class, filter);
// first The first is the tenant's highest priority.
Optional<UserService> optional = userServices.stream().findFirst();

Here's an example code snippet demonstrating how a plugin can retrieve configuration:

public class Boot extends AbstractBoot {
    // 定义配置, key name 和 Default value;
   public static ConfigSupport configSupport = new ConfigSupport("bv2", null);
}
public String hello() {
   return configSupport.getProperty();
}

springboot config(-D or application.yml):

plugins_path={Plugin directory that exp actively loads when springboot starts}
plugins_work_dir={exp's working directory, which will extract the code into this directory, subdirectory named plugin id}
plugins_auto_delete_enable={Whether to automatically delete the existing plugin directory}
plugins_spring_url_replace_enable={Whether the plug-in can override the main program url, note that multi-tenant level override is not currently supported}
exp_object_field_config_json={The plug-in dynamically adds fields json, json 结构定义见: cn.think.in.java.open.exp.object.field.ext.ExtMetaBean}

License

Apache 2.0 License.

Stargazers over time

Stargazers over time

exp's People

Contributors

stateis0 avatar jujiale avatar neo0820 avatar alg-psy avatar lin1005q avatar zhanglijun1217 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.