spring-plugin简单使用

spring-plugin 是spring 官方提供的一个插件化设计方案,比如使用支持基于spring 的项目

项目结构

此简单测试项目是一个maven 多模块的,包含了一个plugin 契约模块,连个插件实现,以及一个bootstrap 启动入口

  • 代码结构
├── README.md
├── bootstrap
├── HELP.md
├── pom.xml
└── src
└── main
├── java
└── com
└── dalongplugin
└── bootstrap
├── BootstrapApplication.java
└── demos
└── web
└── Api.java
└── resources
├── application.properties
└── static
└── index.html
├── plugin_a
├── pom.xml
└── src
├── main
├── java
└── com
└── dalongplugina
└── PluginA.java
└── resources
└── test
└── java
├── plugin_b
├── pom.xml
└── src
├── main
├── java
└── com
└── dalongpluginb
└── PluginB.java
└── resources
└── test
└── java
├── plugin_interface
├── pom.xml
└── src
├── main
├── java
└── com
└── dalongpluginb
└── PluginContract.java
└── resources
└── test
└── java
└── pom.xml

代码说明

  • plugin_interface
    就是一个接口定义
 
package com.dalongpluginb;
 
import org.springframework.plugin.core.Plugin;
 
public interface PluginContract extends Plugin<String> {
    String message(String input);
}

引用的包

<dependencies>
        <dependency>
            <groupId>org.springframework.plugin</groupId>
            <artifactId>spring-plugin-core</artifactId>
        </dependency>
</dependencies>
  • plugina 实现
package com.dalongplugina;
 
import com.dalongpluginb.PluginContract;
import org.springframework.stereotype.Component;
 
@Component
public class PluginA implements PluginContract {
    @Override
    public String message(String input) {
        return String.format("plugina: %s", input);
    }
    @Override
    public boolean supports(String s) {
        return s.equalsIgnoreCase("plugina");
    }
}

maven 依赖

<dependencies>
        <dependency>
            <groupId>com.dalong</groupId>
            <artifactId>plugin_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>provided</scope>
        </dependency>
</dependencies>

pluginb 类似

  • bootstrap 入口
    一个spring boot 项目,同时会添加插入契约定义,默认是一个spring boot web 项目
    maven 依赖
 
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dalong</groupId>
    <artifactId>bootstrap</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>bootstrap</name>
    <description>bootstrap</description>
    <properties>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.4.2</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
       // spring-plugin 依赖添加
        <dependency>
            <groupId>org.springframework.plugin</groupId>
            <artifactId>spring-plugin-core</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.plugin</groupId>
            <artifactId>spring-plugin-metadata</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.dalong</groupId>
            <artifactId>plugin_a</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.dalong</groupId>
            <artifactId>plugin_b</artifactId>
            <version>1.0-SNAPSHOT</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.dalong</groupId>
            <artifactId>plugin_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
 
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        // 移除jar maven 构建信息 
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
            </plugin>
          // 为了方便插件的加载没有使用spring boot 的fat jar 插件
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>
                                ${project.build.directory}/libs
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
 
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>libs/</classpathPrefix>
                            <mainClass>com.dalongplugin.bootstrap.BootstrapApplication</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
</project>
  • 入口代码
package com.dalongplugin.bootstrap;
 
import com.dalongpluginb.PluginContract;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.plugin.core.PluginRegistry;
import org.springframework.plugin.core.config.EnablePluginRegistries;
 
// 通过scanBasePackages 配置需要进行的包扫描,间接解决插件加载的问题
@SpringBootApplication(scanBasePackages = {"com.dalongpluginb","com.dalongplugin.bootstrap","com.dalongplugina"})
// 进行插件扫描
@EnablePluginRegistries(PluginContract.class)
public class BootstrapApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(BootstrapApplication.class, args);
    }
    // ApplicationRunner 启动之后进行插件的调用,主要是测试
    @Bean
    public ApplicationRunner runner(PluginRegistry<PluginContract,String> plugins) {
        return args -> {
            plugins.forEach(plugin -> {
                System.out.println(plugin.message("hello"));
            });
        };
    }
}

使用效果

因为默认本地开发插件都加载了(maven 配置了),因为我们使用的是通过外部classpath 模式,所以可以随时进行插件的添加以及移除

  • 构建
mvn clean package
  • bootstrap 效果
├── bootstrap-0.0.1-SNAPSHOT.jar
└── libs
    ├── accessors-smart-1.2.jar
    ├── android-json-0.0.20131108.vaadin1.jar
    ├── apiguardian-api-1.1.0.jar
    ├── asm-5.0.4.jar
    ├── assertj-core-3.18.1.jar
    ├── byte-buddy-1.10.19.jar
    ├── byte-buddy-agent-1.10.19.jar
    ├── hamcrest-2.2.jar
    ├── jackson-annotations-2.11.4.jar
    ├── jackson-core-2.11.4.jar
    ├── jackson-databind-2.11.4.jar
    ├── jackson-datatype-jdk8-2.11.4.jar
    ├── jackson-datatype-jsr310-2.11.4.jar
    ├── jackson-module-parameter-names-2.11.4.jar
    ├── jakarta.activation-api-1.2.2.jar
    ├── jakarta.annotation-api-1.3.5.jar
    ├── jakarta.el-3.0.3.jar
    ├── jakarta.xml.bind-api-2.3.3.jar
    ├── json-path-2.4.0.jar
    ├── json-smart-2.3.jar
    ├── jsonassert-1.5.0.jar
    ├── jul-to-slf4j-1.7.30.jar
    ├── junit-jupiter-5.7.0.jar
    ├── junit-jupiter-api-5.7.0.jar
    ├── junit-jupiter-engine-5.7.0.jar
    ├── junit-jupiter-params-5.7.0.jar
    ├── junit-platform-commons-1.7.0.jar
    ├── junit-platform-engine-1.7.0.jar
    ├── log4j-api-2.13.3.jar
    ├── log4j-to-slf4j-2.13.3.jar
    ├── logback-classic-1.2.3.jar
    ├── logback-core-1.2.3.jar
    ├── mockito-core-3.6.28.jar
    ├── mockito-junit-jupiter-3.6.28.jar
    ├── objenesis-3.1.jar
    ├── opentest4j-1.2.0.jar
    ├── plugin_a-1.0-SNAPSHOT.jar
    ├── plugin_b-1.0-SNAPSHOT.jar
    ├── plugin_interface-1.0-SNAPSHOT.jar
    ├── slf4j-api-1.7.30.jar
    ├── snakeyaml-1.27.jar
    ├── spring-aop-5.3.3.jar
    ├── spring-beans-5.3.3.jar
    ├── spring-boot-2.4.2.jar
    ├── spring-boot-autoconfigure-2.4.2.jar
    ├── spring-boot-starter-2.4.2.jar
    ├── spring-boot-starter-json-2.4.2.jar
    ├── spring-boot-starter-logging-2.4.2.jar
    ├── spring-boot-starter-test-2.4.2.jar
    ├── spring-boot-starter-tomcat-2.4.2.jar
    ├── spring-boot-starter-web-2.4.2.jar
    ├── spring-boot-test-2.4.2.jar
    ├── spring-boot-test-autoconfigure-2.4.2.jar
    ├── spring-context-5.3.3.jar
    ├── spring-core-5.3.3.jar
    ├── spring-expression-5.3.3.jar
    ├── spring-jcl-5.3.3.jar
    ├── spring-plugin-core-2.0.0.RELEASE.jar
    ├── spring-plugin-metadata-2.0.0.RELEASE.jar
    ├── spring-test-5.3.3.jar
    ├── spring-web-5.3.3.jar
    ├── spring-webmvc-5.3.3.jar
    ├── tomcat-embed-core-9.0.41.jar
    ├── tomcat-embed-websocket-9.0.41.jar
    └── xmlunit-core-2.7.0.jar

默认运行效果

移除一个插件的效果

说明

实际上目前也是有不少缺陷的,比如类java,外部jar 加载,以及类隔离的一些问题,同时也缺少维护了,但是对于简单项目还是很不错的,可以使用

参考资料

https://github.com/spring-projects/spring-plugin
https://github.com/rongfengliang/spring-plugin-learning

posted on 2024-02-05 09:31  荣锋亮  阅读(215)  评论(0编辑  收藏  举报

导航