feat:加入spring-brick和plugin-core
parent
b047655808
commit
71e74d447e
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>iot-common-core</artifactId>
|
<artifactId>iot-common-core</artifactId>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -30,6 +30,11 @@
|
||||||
<artifactId>easyexcel</artifactId>
|
<artifactId>easyexcel</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.xmlbeans</groupId>
|
||||||
|
<artifactId>xmlbeans</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-message-bus</artifactId>
|
<artifactId>iot-message-bus</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-message-bus</artifactId>
|
<artifactId>iot-message-bus</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-message-bus</artifactId>
|
<artifactId>iot-message-bus</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cc.iotkit</groupId>
|
||||||
|
<artifactId>iot-iita-core</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>iot-plugin-core</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
|
<spring-brick.version>3.1.4</spring-brick.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cc.iotkit</groupId>
|
||||||
|
<artifactId>iot-common-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cc.iotkit</groupId>
|
||||||
|
<artifactId>iot-script-engine</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cc.iotkit</groupId>
|
||||||
|
<artifactId>iot-message-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--====================第三方库===================-->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.starblues</groupId>
|
||||||
|
<artifactId>spring-brick</artifactId>
|
||||||
|
<version>${spring-brick.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,22 @@
|
||||||
|
package cc.iotkit.plugin.core;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件接口
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public interface IPlugin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备连接信息,如连接mqtt的ip、端口、账号、密码。。。
|
||||||
|
*
|
||||||
|
* @param pk 产品key
|
||||||
|
* @param dn 设备dn
|
||||||
|
* @return 连接配置项
|
||||||
|
*/
|
||||||
|
Map<String, Object> getLinkInfo(String pk, String dn);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cc.iotkit.plugin.core;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件配置接口
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public interface IPluginConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取系统中配置的插件配置项
|
||||||
|
*
|
||||||
|
* @param pluginId 插件id
|
||||||
|
* @return config
|
||||||
|
*/
|
||||||
|
Map<String, Object> getConfig(String pluginId);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package cc.iotkit.plugin.core;
|
||||||
|
|
||||||
|
import cc.iotkit.script.IScriptEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件宿主接口
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public interface IPluginScript {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取插件对应的脚本引擎
|
||||||
|
*
|
||||||
|
* @param pluginId 插件id
|
||||||
|
* @return IScriptEngine
|
||||||
|
*/
|
||||||
|
IScriptEngine getScriptEngine(String pluginId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新加载脚本
|
||||||
|
*
|
||||||
|
* @param pluginId 插件id
|
||||||
|
*/
|
||||||
|
void reloadScript(String pluginId);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cc.iotkit.plugin.core;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地独立运行的插件配置
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public class LocalPluginConfig implements IPluginConfig {
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getConfig(String pluginId) {
|
||||||
|
//本地的直接用程序中默认值
|
||||||
|
return new HashMap<>(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package cc.iotkit.plugin.core;
|
||||||
|
|
||||||
|
import cc.iotkit.common.utils.StringUtils;
|
||||||
|
import cc.iotkit.common.utils.file.FileUtils;
|
||||||
|
import cc.iotkit.script.IScriptEngine;
|
||||||
|
import cc.iotkit.script.ScriptEngineFactory;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地独立运行的插件脚本实现
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public class LocalPluginScript implements IPluginScript {
|
||||||
|
|
||||||
|
private IScriptEngine scriptEngine;
|
||||||
|
|
||||||
|
public LocalPluginScript(String scriptPath) {
|
||||||
|
if (StringUtils.isBlank(scriptPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
URL resource = LocalPluginScript.class.getClassLoader().getResource(scriptPath);
|
||||||
|
if (resource == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String script = FileUtils.readString(resource.getFile(), Charset.defaultCharset());
|
||||||
|
initScriptEngine(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IScriptEngine initScriptEngine(String script) {
|
||||||
|
if (StringUtils.isBlank(script)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptEngine = ScriptEngineFactory.getJsEngine(script);
|
||||||
|
return scriptEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IScriptEngine getScriptEngine(String pluginId) {
|
||||||
|
return scriptEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reloadScript(String pluginId) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package cc.iotkit.plugin.core.thing;
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionResult;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.down.DeviceConfig;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.down.PropertyGet;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.down.PropertySet;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.down.ServiceInvoke;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备接口
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public interface IDevice {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行设备配置动作
|
||||||
|
*
|
||||||
|
* @param action 动作
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
ActionResult config(DeviceConfig action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行设备属性获取动作
|
||||||
|
*
|
||||||
|
* @param action 动作
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
ActionResult propertyGet(PropertyGet action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行设备属性设置动作
|
||||||
|
*
|
||||||
|
* @param action 动作
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
ActionResult propertySet(PropertySet action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行设备服务调用动作
|
||||||
|
*
|
||||||
|
* @param action 动作
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
ActionResult serviceInvoke(ServiceInvoke action);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package cc.iotkit.plugin.core.thing;
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionResult;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.IDeviceAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.model.ThingDevice;
|
||||||
|
import cc.iotkit.plugin.core.thing.model.ThingProduct;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备服务接口
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public interface IThingService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交设备行为
|
||||||
|
*
|
||||||
|
* @param action IDeviceAction
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
ActionResult post(String pluginId, IDeviceAction action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取产品信息
|
||||||
|
*
|
||||||
|
* @param pk 产品key
|
||||||
|
* @return Product
|
||||||
|
*/
|
||||||
|
ThingProduct getProduct(String pk);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备信息
|
||||||
|
*
|
||||||
|
* @param deviceName 设备dn
|
||||||
|
* @return DeviceInfo
|
||||||
|
*/
|
||||||
|
ThingDevice getDevice(String deviceName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备当前属性数据
|
||||||
|
*
|
||||||
|
* @param deviceName 设备dn
|
||||||
|
* @return 当前属性
|
||||||
|
*/
|
||||||
|
Map<String, ?> getProperty(String deviceName);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public abstract class AbstractAction implements IDeviceAction {
|
||||||
|
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
protected ActionType type;
|
||||||
|
|
||||||
|
protected String productKey;
|
||||||
|
|
||||||
|
protected String deviceName;
|
||||||
|
|
||||||
|
protected Long time;
|
||||||
|
|
||||||
|
public AbstractAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractAction(ActionType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动作执行结果
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class ActionResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码,0:成功,x:其它错误码
|
||||||
|
*/
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败原因
|
||||||
|
*/
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备物行为类型
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum ActionType {
|
||||||
|
|
||||||
|
//注册
|
||||||
|
REGISTER("register"),
|
||||||
|
//设备拓扑更新
|
||||||
|
TOPOLOGY("topology"),
|
||||||
|
//在离线状态变更
|
||||||
|
STATE_CHANGE("state_change"),
|
||||||
|
//属性上报
|
||||||
|
PROPERTY_REPORT("property_report"),
|
||||||
|
//事件上报
|
||||||
|
EVENT_REPORT("event_report"),
|
||||||
|
//服务回复
|
||||||
|
SERVICE_REPLY("service_reply"),
|
||||||
|
|
||||||
|
//属性设置
|
||||||
|
PROPERTY_SET("property_set"),
|
||||||
|
//属性获取
|
||||||
|
PROPERTY_GET("property_get"),
|
||||||
|
//服务调用
|
||||||
|
SERVICE_INVOKE("service_invoke"),
|
||||||
|
//配置
|
||||||
|
CONFIG("config");
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备状态
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum DeviceState {
|
||||||
|
|
||||||
|
//在线
|
||||||
|
ONLINE("online"),
|
||||||
|
//离线
|
||||||
|
OFFLINE("offline");
|
||||||
|
|
||||||
|
private final String state;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件级别
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum EventLevel {
|
||||||
|
|
||||||
|
//信息
|
||||||
|
INFO("info"),
|
||||||
|
//告警
|
||||||
|
WARN("warn"),
|
||||||
|
//错误
|
||||||
|
ERROR("error");
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备行为
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
public interface IDeviceAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取唯一标识id
|
||||||
|
*
|
||||||
|
* @return id
|
||||||
|
*/
|
||||||
|
String getId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置id
|
||||||
|
*
|
||||||
|
* @param id id
|
||||||
|
*/
|
||||||
|
void setId(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类型
|
||||||
|
*
|
||||||
|
* @return ActionType
|
||||||
|
*/
|
||||||
|
ActionType getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备类型
|
||||||
|
*
|
||||||
|
* @param type type
|
||||||
|
*/
|
||||||
|
void setType(ActionType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取产品key
|
||||||
|
*
|
||||||
|
* @return ProductKey
|
||||||
|
*/
|
||||||
|
String getProductKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置产品key
|
||||||
|
*
|
||||||
|
* @param productKey pk
|
||||||
|
*/
|
||||||
|
void setProductKey(String productKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备DN
|
||||||
|
*
|
||||||
|
* @return DN
|
||||||
|
*/
|
||||||
|
String getDeviceName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置设备DN
|
||||||
|
*
|
||||||
|
* @param deviceName dn
|
||||||
|
*/
|
||||||
|
void setDeviceName(String deviceName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取时间
|
||||||
|
*
|
||||||
|
* @return timespan
|
||||||
|
*/
|
||||||
|
Long getTime();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置时间
|
||||||
|
*
|
||||||
|
* @param time timestamp
|
||||||
|
*/
|
||||||
|
void setTime(Long time);
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.down;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备配置
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class DeviceConfig extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置模块
|
||||||
|
*/
|
||||||
|
private String module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置信息
|
||||||
|
*/
|
||||||
|
private Map<String, Object> config;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.CONFIG;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.down;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性获取
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class PropertyGet extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性列表
|
||||||
|
*/
|
||||||
|
private List<String> keys;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.PROPERTY_GET;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.down;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性设置
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class PropertySet extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性参数
|
||||||
|
*/
|
||||||
|
private Map<String, ?> params;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.PROPERTY_SET;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.down;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务调用
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
public class ServiceInvoke extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务参数
|
||||||
|
*/
|
||||||
|
private Map<String, ?> params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置信息
|
||||||
|
*/
|
||||||
|
private Map<String, ?> config;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.SERVICE_INVOKE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.up;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备注册动作
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class DeviceRegister extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 型号
|
||||||
|
*/
|
||||||
|
private String model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本号
|
||||||
|
*/
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.REGISTER;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.up;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.DeviceState;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备在线状态变更
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class DeviceStateChange extends AbstractAction {
|
||||||
|
|
||||||
|
private DeviceState state;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.STATE_CHANGE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.up;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备拓扑更新
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class DeviceTopology extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父设备下的子设备列表
|
||||||
|
*/
|
||||||
|
private List<String> subDevices;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.TOPOLOGY;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.up;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.EventLevel;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件上报
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class EventReport extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件级别
|
||||||
|
*/
|
||||||
|
private EventLevel level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 事件参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> params;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.EVENT_REPORT;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.up;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性上报
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class PropertyReport extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> params;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.PROPERTY_REPORT;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.actions.up;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.AbstractAction;
|
||||||
|
import cc.iotkit.plugin.core.thing.actions.ActionType;
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务回复
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SuperBuilder
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class ServiceReply extends AbstractAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回复服务id
|
||||||
|
*/
|
||||||
|
private String replyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码,0:成功,x:失败错误码
|
||||||
|
*/
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务回复参数
|
||||||
|
*/
|
||||||
|
private Map<String, Object> params;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionType getType() {
|
||||||
|
return ActionType.SERVICE_REPLY;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备信息
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class ThingDevice {
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品key
|
||||||
|
*/
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备dn
|
||||||
|
*/
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备型号
|
||||||
|
*/
|
||||||
|
private String model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备密钥
|
||||||
|
*/
|
||||||
|
private String secret;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package cc.iotkit.plugin.core.thing.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品信息
|
||||||
|
*
|
||||||
|
* @author sjg
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class ThingProduct {
|
||||||
|
|
||||||
|
private String productKey;
|
||||||
|
|
||||||
|
private String productSecret;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
private Integer nodeType;
|
||||||
|
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>iot-iita-core</artifactId>
|
<artifactId>iot-iita-core</artifactId>
|
||||||
<groupId>cc.iotkit</groupId>
|
<groupId>cc.iotkit</groupId>
|
||||||
<version>1.0.1</version>
|
<version>1.0.2</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>iot-script-engine</artifactId>
|
<artifactId>iot-script-engine</artifactId>
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cc.iotkit</groupId>
|
||||||
|
<artifactId>iot-iita-core</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>com.gitee.starblues</groupId>
|
||||||
|
<artifactId>iot-spring-brick</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>3.1.4</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>spring-brick-common</module>
|
||||||
|
<module>spring-brick-loader</module>
|
||||||
|
<module>spring-brick</module>
|
||||||
|
<module>spring-brick-bootstrap</module>
|
||||||
|
<module>spring-brick-maven-packager</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>The Apache Software License, Version 2.0</name>
|
||||||
|
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<url>https://gitee.com/starblues/springboot-plugin-framework-parent</url>
|
||||||
|
<connection>scm:https://gitee.com/starblues/springboot-plugin-framework-parent.git</connection>
|
||||||
|
<developerConnection>scm:https://gitee.com/starblues/springboot-plugin-framework-parent.git</developerConnection>
|
||||||
|
<tag>1.0</tag>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>StarBlues</name>
|
||||||
|
<email>starblues@foxmail.com</email>
|
||||||
|
<url>https://gitee.com/starblues/</url>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<plugin.skip>true</plugin.skip>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>release</id>
|
||||||
|
<properties>
|
||||||
|
<plugin.skip>false</plugin.skip>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.gitee.starblues</groupId>
|
||||||
|
<artifactId>iot-spring-brick</artifactId>
|
||||||
|
<version>3.1.4</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>spring-brick-bootstrap</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<description>插件启动引导模块</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.gitee.starblues</groupId>
|
||||||
|
<artifactId>spring-brick</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>${javax.servlet-api.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
|
||||||
|
import com.gitee.starblues.bootstrap.realize.AutowiredTypeDefiner;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置 ClassDefiner
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.3
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public class AutowiredTypeDefinerConfig {
|
||||||
|
|
||||||
|
private final Set<AutowiredTypeDefiner.ClassDefiner> classDefiners;
|
||||||
|
|
||||||
|
public AutowiredTypeDefinerConfig(){
|
||||||
|
this.classDefiners = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<AutowiredTypeDefiner.ClassDefiner> getClassDefiners(){
|
||||||
|
return classDefiners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutowiredTypeDefinerConfig add(AutowiredType.Type type, String... classNamePatterns){
|
||||||
|
if(type != null && classNamePatterns != null && classNamePatterns.length > 0){
|
||||||
|
classDefiners.add(AutowiredTypeDefiner.ClassDefiner.config(type, classNamePatterns));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutowiredTypeDefinerConfig add(AutowiredType.Type type, Class<?>... classes){
|
||||||
|
if(type != null && classes != null && classes.length > 0){
|
||||||
|
classDefiners.add(AutowiredTypeDefiner.ClassDefiner.config(type, classes));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.realize.AutowiredTypeDefiner;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import com.gitee.starblues.utils.UrlUtils;
|
||||||
|
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||||
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
import org.springframework.util.PathMatcher;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入类型处理
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.3
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public interface AutowiredTypeResolver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 descriptor 获取注入类型
|
||||||
|
* @param descriptor descriptor
|
||||||
|
* @return AutowiredType.Type
|
||||||
|
*/
|
||||||
|
AutowiredType.Type resolve(DependencyDescriptor descriptor);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.core.descriptor.InsidePluginDescriptor;
|
||||||
|
import com.gitee.starblues.integration.AutoIntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.integration.IntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.loader.launcher.DevelopmentModeSetting;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.utils.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.LiveBeansView;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.env.MapPropertySource;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件环境配置
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.2
|
||||||
|
*/
|
||||||
|
public class ConfigurePluginEnvironment {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ConfigurePluginEnvironment.class);
|
||||||
|
|
||||||
|
private final static String PLUGIN_PROPERTY_NAME = "pluginPropertySources";
|
||||||
|
|
||||||
|
private final static String SPRING_CONFIG_NAME = "spring.config.name";
|
||||||
|
private final static String SPRING_CONFIG_LOCATION = "spring.config.location";
|
||||||
|
|
||||||
|
private final static String SPRING_JMX_UNIQUE_NAMES = "spring.jmx.unique-names";
|
||||||
|
private final static String SPRING_ADMIM_ENABLED = "spring.application.admin.enabled";
|
||||||
|
private final static String SPRING_ADMIN_JMX_NAME = "spring.application.admin.jmx-name";
|
||||||
|
private final static String SPRING_ADMIN_JMX_VALUE = "org.springframework.boot:type=Admin,name=";
|
||||||
|
|
||||||
|
public static final String REGISTER_SHUTDOWN_HOOK_PROPERTY = "logging.register-shutdown-hook";
|
||||||
|
public static final String MBEAN_DOMAIN_PROPERTY_NAME = "spring.liveBeansView.mbeanDomain";
|
||||||
|
|
||||||
|
private final ProcessorContext processorContext;
|
||||||
|
private final InsidePluginDescriptor pluginDescriptor;
|
||||||
|
|
||||||
|
public ConfigurePluginEnvironment(ProcessorContext processorContext) {
|
||||||
|
this.processorContext = Assert.isNotNull(processorContext, "processorContext 不能为空");
|
||||||
|
this.pluginDescriptor = Assert.isNotNull(processorContext.getPluginDescriptor(),
|
||||||
|
"pluginDescriptor 不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
|
||||||
|
Map<String, Object> env = new HashMap<>();
|
||||||
|
String pluginId = pluginDescriptor.getPluginId();
|
||||||
|
String configFileName = pluginDescriptor.getConfigFileName();
|
||||||
|
if(!ObjectUtils.isEmpty(configFileName)){
|
||||||
|
env.put(SPRING_CONFIG_NAME, PluginFileUtils.getFileName(configFileName));
|
||||||
|
}
|
||||||
|
String configFileLocation = pluginDescriptor.getConfigFileLocation();
|
||||||
|
if(!ObjectUtils.isEmpty(configFileLocation)){
|
||||||
|
env.put(SPRING_CONFIG_LOCATION, getConfigFileLocation(configFileLocation));
|
||||||
|
}
|
||||||
|
env.put(AutoIntegrationConfiguration.ENABLE_STARTER_KEY, false);
|
||||||
|
env.put(SPRING_JMX_UNIQUE_NAMES, true);
|
||||||
|
// 直接禁用插件的 spring-admin mbean
|
||||||
|
env.put(SPRING_ADMIM_ENABLED, false);
|
||||||
|
env.put(SPRING_ADMIN_JMX_NAME, SPRING_ADMIN_JMX_VALUE + pluginId);
|
||||||
|
env.put(REGISTER_SHUTDOWN_HOOK_PROPERTY, false);
|
||||||
|
env.put(MBEAN_DOMAIN_PROPERTY_NAME, pluginId);
|
||||||
|
|
||||||
|
|
||||||
|
try{
|
||||||
|
// fix: https://gitee.com/starblues/springboot-plugin-framework-parent/issues/I57965
|
||||||
|
// 优先注册LiveBeansView对象,防止注册异常
|
||||||
|
Method method = LiveBeansView.class.getDeclaredMethod("registerApplicationContext", ConfigurableApplicationContext.class);
|
||||||
|
method.setAccessible(true);
|
||||||
|
method.invoke(null,processorContext.getApplicationContext());
|
||||||
|
} catch (Exception ex){
|
||||||
|
logger.error("LiveBeansView.registerApplicationContext失败. {}", ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
if(DevelopmentModeSetting.coexist()){
|
||||||
|
env.put(AutoIntegrationConfiguration.ENABLE_STARTER_KEY, false);
|
||||||
|
}
|
||||||
|
configProfiles(environment);
|
||||||
|
environment.getPropertySources().addFirst(new MapPropertySource(PLUGIN_PROPERTY_NAME, env));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logProfiles(ConfigurableEnvironment environment){
|
||||||
|
IntegrationConfiguration configuration = processorContext.getConfiguration();
|
||||||
|
String fromMainMsg = configuration.pluginFollowProfile() ? " from main" : " ";
|
||||||
|
String[] activeProfiles = environment.getActiveProfiles();
|
||||||
|
if(activeProfiles.length > 0){
|
||||||
|
logger.info("Plugin[{}] following profiles are active{}: {}",
|
||||||
|
MsgUtils.getPluginUnique(pluginDescriptor),
|
||||||
|
fromMainMsg,
|
||||||
|
StringUtils.toStrByArray(activeProfiles));
|
||||||
|
} else {
|
||||||
|
logger.info("Plugin[{}] No active profile set, falling back to default profiles{}: {}",
|
||||||
|
MsgUtils.getPluginUnique(pluginDescriptor),
|
||||||
|
fromMainMsg,
|
||||||
|
StringUtils.toStrByArray(environment.getDefaultProfiles()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configProfiles(ConfigurableEnvironment environment){
|
||||||
|
IntegrationConfiguration configuration = processorContext.getConfiguration();
|
||||||
|
if(!configuration.pluginFollowProfile()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MainApplicationContext mainApplicationContext = processorContext.getMainApplicationContext();
|
||||||
|
String[] mainActiveProfiles = mainApplicationContext.getActiveProfiles();
|
||||||
|
if(mainActiveProfiles.length > 0){
|
||||||
|
environment.setActiveProfiles(mainActiveProfiles);
|
||||||
|
} else {
|
||||||
|
logger.info("Plugin[{}] No active profile set, falling back to default profiles: {}",
|
||||||
|
MsgUtils.getPluginUnique(pluginDescriptor),
|
||||||
|
StringUtils.toStrByArray(environment.getDefaultProfiles()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getConfigFileLocation(String configFileLocation){
|
||||||
|
String path = FilesUtils.resolveRelativePath(new File("").getAbsolutePath(), configFileLocation);
|
||||||
|
// 拼接最后字符斜杠
|
||||||
|
if(path.endsWith(FilesUtils.SLASH) || path.endsWith(File.separator)){
|
||||||
|
return path;
|
||||||
|
} else {
|
||||||
|
return path + File.separator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.realize.AutowiredTypeDefiner;
|
||||||
|
import com.gitee.starblues.utils.UrlUtils;
|
||||||
|
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||||
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
import org.springframework.util.PathMatcher;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认的 AutowiredTypeResolver 实现
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public class DefaultAutowiredTypeResolver implements AutowiredTypeResolver{
|
||||||
|
|
||||||
|
|
||||||
|
private final Set<AutowiredTypeDefiner.ClassDefiner> classDefiners;
|
||||||
|
private final PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
|
|
||||||
|
|
||||||
|
public DefaultAutowiredTypeResolver(ProcessorContext processorContext) {
|
||||||
|
AutowiredTypeDefiner autowiredTypeDefiner = processorContext.getSpringPluginBootstrap().autowiredTypeDefiner();
|
||||||
|
if(autowiredTypeDefiner != null){
|
||||||
|
AutowiredTypeDefinerConfig definerConfig = new AutowiredTypeDefinerConfig();
|
||||||
|
autowiredTypeDefiner.config(definerConfig);
|
||||||
|
classDefiners = definerConfig.getClassDefiners();
|
||||||
|
} else {
|
||||||
|
classDefiners = Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AutowiredType.Type resolve(DependencyDescriptor descriptor){
|
||||||
|
String name = descriptor.getDependencyType().getName();
|
||||||
|
String classNamePath = UrlUtils.formatMatchUrl(name);
|
||||||
|
for (AutowiredTypeDefiner.ClassDefiner classDefiner : classDefiners) {
|
||||||
|
Set<String> classNamePatterns = classDefiner.getClassNamePatterns();
|
||||||
|
for (String classNamePattern : classNamePatterns) {
|
||||||
|
if(pathMatcher.match(classNamePattern, classNamePath)){
|
||||||
|
return classDefiner.getAutowiredType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AutowiredType autowiredType = descriptor.getAnnotation(AutowiredType.class);
|
||||||
|
if(autowiredType != null){
|
||||||
|
return autowiredType.value();
|
||||||
|
} else {
|
||||||
|
return AutowiredType.Type.PLUGIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.realize.PluginCloseListener;
|
||||||
|
import com.gitee.starblues.bootstrap.realize.StopValidator;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.DestroyUtils;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.SpringBeanUtils;
|
||||||
|
import com.gitee.starblues.core.PluginCloseType;
|
||||||
|
import com.gitee.starblues.core.exception.PluginProhibitStopException;
|
||||||
|
import com.gitee.starblues.spring.ApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.ApplicationContextProxy;
|
||||||
|
import com.gitee.starblues.spring.SpringPluginHook;
|
||||||
|
import com.gitee.starblues.spring.WebConfig;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认的插件钩子器
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public class DefaultSpringPluginHook implements SpringPluginHook {
|
||||||
|
|
||||||
|
protected final SpringPluginProcessor pluginProcessor;
|
||||||
|
protected final ProcessorContext processorContext;
|
||||||
|
private final StopValidator stopValidator;
|
||||||
|
|
||||||
|
public DefaultSpringPluginHook(SpringPluginProcessor pluginProcessor,
|
||||||
|
ProcessorContext processorContext) {
|
||||||
|
this.pluginProcessor = pluginProcessor;
|
||||||
|
this.processorContext = processorContext;
|
||||||
|
this.stopValidator = SpringBeanUtils.getExistBean(processorContext.getApplicationContext(),
|
||||||
|
StopValidator.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 先校验是否可卸载
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void stopVerify() {
|
||||||
|
if(stopValidator == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
StopValidator.Result result = stopValidator.verify();
|
||||||
|
if(result != null && !result.isVerify()){
|
||||||
|
throw new PluginProhibitStopException(processorContext.getPluginDescriptor(),
|
||||||
|
result.getMessage());
|
||||||
|
}
|
||||||
|
} catch (Exception e){
|
||||||
|
throw new PluginProhibitStopException(processorContext.getPluginDescriptor(),
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(PluginCloseType closeType) throws Exception{
|
||||||
|
try {
|
||||||
|
GenericApplicationContext applicationContext = processorContext.getApplicationContext();
|
||||||
|
callPluginCloseListener(applicationContext, closeType);
|
||||||
|
pluginProcessor.close(processorContext);
|
||||||
|
applicationContext.close();
|
||||||
|
processorContext.clearRegistryInfo();
|
||||||
|
DestroyUtils.destroyAll(null, SpringFactoriesLoader.class, "cache", Map.class);
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
SpringPluginBootstrapBinder.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationContext getApplicationContext() {
|
||||||
|
return new ApplicationContextProxy(processorContext.getApplicationContext().getBeanFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebConfig getWebConfig() {
|
||||||
|
return processorContext.getWebConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void callPluginCloseListener(GenericApplicationContext applicationContext, PluginCloseType closeType){
|
||||||
|
List<PluginCloseListener> pluginCloseListeners = SpringBeanUtils.getBeans(
|
||||||
|
applicationContext, PluginCloseListener.class);
|
||||||
|
if(pluginCloseListeners.isEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (PluginCloseListener pluginCloseListener : pluginCloseListeners) {
|
||||||
|
try {
|
||||||
|
pluginCloseListener.close(applicationContext, processorContext.getPluginInfo(), closeType);
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.SpringBeanFactory;
|
||||||
|
import com.gitee.starblues.spring.environment.EmptyEnvironmentProvider;
|
||||||
|
import com.gitee.starblues.spring.environment.EnvironmentProvider;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空的MainApplicationContext实现
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.1
|
||||||
|
*/
|
||||||
|
public class EmptyMainApplicationContext implements MainApplicationContext {
|
||||||
|
|
||||||
|
private final SpringBeanFactory springBeanFactory = new EmptySpringBeanFactory();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpringBeanFactory getSpringBeanFactory() {
|
||||||
|
return springBeanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSourceBeanFactory() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Map<String, Object>> getConfigurableEnvironment() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnvironmentProvider getEnvironmentProvider() {
|
||||||
|
return new EmptyEnvironmentProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getActiveProfiles() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getDefaultProfiles() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object resolveDependency(String requestingBeanName, Class<?> dependencyType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWebEnvironment() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSourceApplicationContext() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegisterController() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.spring.SpringBeanFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 空的 SpringBeanFactory 实现
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class EmptySpringBeanFactory implements SpringBeanFactory {
|
||||||
|
@Override
|
||||||
|
public boolean containsBeanDefinition(String beanName) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBeanDefinitionCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBeanDefinitionNames() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBeanNamesForType(ResolvableType type) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBeanNamesForType(Class<?> type) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <A extends Annotation> A findAnnotationOnBean(String s, Class<A> aClass, boolean b) throws NoSuchBeanDefinitionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getBean(String name) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getBean(String name, Object... args) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getBean(Class<T> requiredType) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsBean(String name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getAliases(String name) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.core.descriptor.PluginDescriptor;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件ApplicationContext实现
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public class PluginApplicationContext extends AnnotationConfigApplicationContext {
|
||||||
|
|
||||||
|
private final PluginDescriptor pluginDescriptor;
|
||||||
|
|
||||||
|
public PluginApplicationContext(DefaultListableBeanFactory beanFactory,
|
||||||
|
ProcessorContext processorContext) {
|
||||||
|
super(beanFactory);
|
||||||
|
setResourceLoader(processorContext.getResourceLoader());
|
||||||
|
this.pluginDescriptor = processorContext.getPluginDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerShutdownHook() {
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getApplicationName() {
|
||||||
|
return pluginDescriptor.getPluginId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refresh() throws BeansException, IllegalStateException {
|
||||||
|
super.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.core.descriptor.InsidePluginDescriptor;
|
||||||
|
import com.gitee.starblues.integration.IntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.spring.SpringBeanFactory;
|
||||||
|
import com.gitee.starblues.spring.environment.EnvironmentProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供插件上下文的工具类
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public abstract class PluginContextHolder {
|
||||||
|
|
||||||
|
private static volatile Boolean INITIALIZED = false;
|
||||||
|
|
||||||
|
private static ProcessorContext processorContext;
|
||||||
|
|
||||||
|
private static ClassLoader pluginClassLoader;
|
||||||
|
private static InsidePluginDescriptor pluginDescriptor;
|
||||||
|
|
||||||
|
private static IntegrationConfiguration configuration;
|
||||||
|
private static Boolean mainIsWebEnv;
|
||||||
|
private static SpringBeanFactory mainSpringBeanFactory;
|
||||||
|
|
||||||
|
|
||||||
|
private PluginContextHolder(){}
|
||||||
|
|
||||||
|
static void initialize(ProcessorContext processorContext){
|
||||||
|
if(INITIALIZED){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PluginContextHolder.processorContext = processorContext;
|
||||||
|
|
||||||
|
PluginContextHolder.pluginClassLoader = processorContext.getClassLoader();
|
||||||
|
PluginContextHolder.pluginDescriptor = processorContext.getPluginDescriptor();
|
||||||
|
PluginContextHolder.configuration = processorContext.getConfiguration();
|
||||||
|
PluginContextHolder.mainIsWebEnv = processorContext.getMainApplicationContext().isWebEnvironment();
|
||||||
|
PluginContextHolder.mainSpringBeanFactory = processorContext.getMainBeanFactory();
|
||||||
|
INITIALIZED = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主程序环境中配置文件内容提供者
|
||||||
|
* @return EnvironmentProvider
|
||||||
|
*/
|
||||||
|
public static EnvironmentProvider getEnvironmentProvider(){
|
||||||
|
check();
|
||||||
|
return processorContext.getMainApplicationContext().getEnvironmentProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主程序针对本框架的配置内容
|
||||||
|
* @return IntegrationConfiguration
|
||||||
|
*/
|
||||||
|
public static IntegrationConfiguration getConfiguration() {
|
||||||
|
check();
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主程序的 SpringBeanFactory . 通过它可获取主程序中的Bean
|
||||||
|
* @return SpringBeanFactory
|
||||||
|
*/
|
||||||
|
public static SpringBeanFactory getMainSpringBeanFactory() {
|
||||||
|
check();
|
||||||
|
return mainSpringBeanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断主程序是否为web环境
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
public static Boolean getMainIsWebEnv() {
|
||||||
|
check();
|
||||||
|
return mainIsWebEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取插件的 classloader
|
||||||
|
* @return ClassLoader
|
||||||
|
*/
|
||||||
|
public static ClassLoader getPluginClassLoader() {
|
||||||
|
check();
|
||||||
|
return pluginClassLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取插件信息
|
||||||
|
* @return InsidePluginDescriptor
|
||||||
|
*/
|
||||||
|
public static InsidePluginDescriptor getPluginDescriptor() {
|
||||||
|
check();
|
||||||
|
return pluginDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(){
|
||||||
|
if(!INITIALIZED){
|
||||||
|
throw new IllegalStateException("PluginContextHolder 未初始化");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.coexist.CoexistAllowAutoConfiguration;
|
||||||
|
import com.gitee.starblues.common.PluginDisableAutoConfig;
|
||||||
|
import com.gitee.starblues.loader.launcher.DevelopmentModeSetting;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件禁用的 AutoConfiguration
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @version 3.1.0
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public class PluginDisableAutoConfiguration implements AutoConfigurationImportFilter {
|
||||||
|
|
||||||
|
private static final ThreadLocal<Boolean> LAUNCH_PLUGIN = new ThreadLocal<Boolean>();
|
||||||
|
|
||||||
|
public PluginDisableAutoConfiguration(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setLaunchPlugin() {
|
||||||
|
LAUNCH_PLUGIN.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
|
||||||
|
if(DevelopmentModeSetting.isolation()){
|
||||||
|
return new IsolationDisableAutoConfiguration().match(autoConfigurationClasses, autoConfigurationMetadata);
|
||||||
|
} else if(DevelopmentModeSetting.coexist()){
|
||||||
|
return new CoexistDisableAutoConfiguration().match(autoConfigurationClasses, autoConfigurationMetadata);
|
||||||
|
} else {
|
||||||
|
boolean[] permitAll = new boolean[autoConfigurationClasses.length];
|
||||||
|
for (int i = 0; i < autoConfigurationClasses.length; i++) {
|
||||||
|
permitAll[i] = permit(
|
||||||
|
PluginDisableAutoConfig.getCommonPluginDisableAutoConfig(),
|
||||||
|
autoConfigurationClasses[i]);
|
||||||
|
}
|
||||||
|
return permitAll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean permit(Collection<String> disableCollection, String className){
|
||||||
|
if(ObjectUtils.isEmpty(className)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (String disableFuzzyClass : disableCollection) {
|
||||||
|
if (className.contains(disableFuzzyClass)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class IsolationDisableAutoConfiguration implements AutoConfigurationImportFilter{
|
||||||
|
|
||||||
|
private final List<String> disableFuzzyClass = new ArrayList<>();
|
||||||
|
|
||||||
|
IsolationDisableAutoConfiguration(){
|
||||||
|
addDisableFuzzyClasses();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDisableFuzzyClasses() {
|
||||||
|
disableFuzzyClass.add("org.springframework.boot.autoconfigure.http");
|
||||||
|
disableFuzzyClass.add("org.springframework.boot.autoconfigure.web");
|
||||||
|
disableFuzzyClass.add("org.springframework.boot.autoconfigure.websocket");
|
||||||
|
disableFuzzyClass.add("org.springframework.boot.autoconfigure.jackson");
|
||||||
|
disableFuzzyClass.add("org.springframework.boot.autoconfigure.webservices");
|
||||||
|
disableFuzzyClass.addAll(PluginDisableAutoConfig.getCommonPluginDisableAutoConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
|
||||||
|
boolean[] match = new boolean[autoConfigurationClasses.length];
|
||||||
|
for (int i = 0; i < autoConfigurationClasses.length; i++) {
|
||||||
|
String autoConfigurationClass = autoConfigurationClasses[i];
|
||||||
|
if(autoConfigurationClass == null || "".equals(autoConfigurationClass)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match[i] = permit(disableFuzzyClass, autoConfigurationClass);
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class CoexistDisableAutoConfiguration implements AutoConfigurationImportFilter{
|
||||||
|
|
||||||
|
public CoexistDisableAutoConfiguration(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
|
||||||
|
Boolean launchPlugin = LAUNCH_PLUGIN.get();
|
||||||
|
boolean[] match = new boolean[autoConfigurationClasses.length];
|
||||||
|
try {
|
||||||
|
if(launchPlugin != null && launchPlugin){
|
||||||
|
CoexistAllowAutoConfiguration configuration = SpringPluginBootstrapBinder.get()
|
||||||
|
.getCoexistAllowAutoConfiguration();
|
||||||
|
for (int i = 0; i < autoConfigurationClasses.length; i++) {
|
||||||
|
String autoConfigurationClass = autoConfigurationClasses[i];
|
||||||
|
if(ObjectUtils.isEmpty(autoConfigurationClass)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(permit(PluginDisableAutoConfig.getCommonPluginDisableAutoConfig(), autoConfigurationClass)){
|
||||||
|
match[i] = configuration.match(autoConfigurationClass);
|
||||||
|
} else {
|
||||||
|
match[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < autoConfigurationClasses.length; i++) {
|
||||||
|
match[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
} finally {
|
||||||
|
LAUNCH_PLUGIN.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,364 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.DestroyUtils;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.SpringBeanFactory;
|
||||||
|
import com.gitee.starblues.utils.ReflectionUtils;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.TypeConverter;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件BeanFactory实现
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.3
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public class PluginListableBeanFactory extends DefaultListableBeanFactory {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(PluginListableBeanFactory.class);
|
||||||
|
|
||||||
|
private final MainApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private AutowiredTypeResolver autowiredTypeResolver;
|
||||||
|
|
||||||
|
public PluginListableBeanFactory(ProcessorContext processorContext) {
|
||||||
|
this.applicationContext = processorContext.getMainApplicationContext();
|
||||||
|
this.autowiredTypeResolver = getAutowiredTypeResolver(processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AutowiredTypeResolver getAutowiredTypeResolver(ProcessorContext processorContext){
|
||||||
|
return new DefaultAutowiredTypeResolver(processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Object resolveDependency(DependencyDescriptor descriptor,
|
||||||
|
@Nullable String requestingBeanName,
|
||||||
|
@Nullable Set<String> autowiredBeanNames,
|
||||||
|
@Nullable TypeConverter typeConverter) throws BeansException {
|
||||||
|
AutowiredType.Type autowiredType = getAutowiredType(descriptor);
|
||||||
|
Class<?> dependencyType = descriptor.getDependencyType();
|
||||||
|
if (dependencyType == ObjectFactory.class || dependencyType == ObjectProvider.class) {
|
||||||
|
Object dependencyObj = super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames,
|
||||||
|
typeConverter);
|
||||||
|
ObjectProvider<Object> provider = (ObjectProvider<Object>) dependencyObj;
|
||||||
|
return new PluginObjectProviderWrapper(provider, requestingBeanName, descriptor, autowiredType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(autowiredType == AutowiredType.Type.MAIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
throw new NoSuchBeanDefinitionException(descriptor.getDependencyType());
|
||||||
|
} else if(autowiredType == AutowiredType.Type.PLUGIN){
|
||||||
|
return super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
|
||||||
|
} else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){
|
||||||
|
try {
|
||||||
|
return super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames,
|
||||||
|
typeConverter);
|
||||||
|
} catch (BeansException e){
|
||||||
|
if(e instanceof NoSuchBeanDefinitionException){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj instanceof ObjectProvider){
|
||||||
|
ObjectProvider<Object> provider = (ObjectProvider<Object>) dependencyObj;
|
||||||
|
return new PluginObjectProviderWrapper(provider, requestingBeanName, descriptor, autowiredType);
|
||||||
|
}
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
return super.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames,
|
||||||
|
typeConverter);
|
||||||
|
}
|
||||||
|
throw new NoSuchBeanDefinitionException(descriptor.getDependencyType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroySingletons() {
|
||||||
|
String[] beanDefinitionNames = getBeanDefinitionNames();
|
||||||
|
for (String beanDefinitionName : beanDefinitionNames) {
|
||||||
|
destroyBean(beanDefinitionName);
|
||||||
|
}
|
||||||
|
super.destroySingletons();
|
||||||
|
destroyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit) {
|
||||||
|
return super.getBeanProvider(requiredType, allowEagerInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AutowiredType.Type getAutowiredType(DependencyDescriptor descriptor){
|
||||||
|
return autowiredTypeResolver.resolve(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object resolveDependencyFromMain(String requestingBeanName, DependencyDescriptor descriptor){
|
||||||
|
Object dependencyObj = null;
|
||||||
|
try {
|
||||||
|
dependencyObj = applicationContext.resolveDependency(requestingBeanName,
|
||||||
|
descriptor.getDependencyType());
|
||||||
|
} catch (Exception e){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void destroyAll(){
|
||||||
|
ReflectionUtils.findField(this.getClass(), field -> {
|
||||||
|
field.setAccessible(true);
|
||||||
|
try {
|
||||||
|
Object o = field.get(this);
|
||||||
|
DestroyUtils.destroyAll(o);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class PluginObjectProviderWrapper implements ObjectProvider<Object> {
|
||||||
|
|
||||||
|
private final ObjectProvider<Object> pluginObjectProvider;
|
||||||
|
|
||||||
|
private final String requestingBeanName;
|
||||||
|
private final DependencyDescriptor descriptor;
|
||||||
|
private final AutowiredType.Type autowiredType;
|
||||||
|
|
||||||
|
private PluginObjectProviderWrapper(ObjectProvider<Object> pluginObjectProvider,
|
||||||
|
String requestingBeanName,
|
||||||
|
DependencyDescriptor descriptor,
|
||||||
|
AutowiredType.Type autowiredType) {
|
||||||
|
this.pluginObjectProvider = pluginObjectProvider;
|
||||||
|
this.requestingBeanName = requestingBeanName;
|
||||||
|
this.descriptor = new NestedDependencyDescriptor(descriptor);
|
||||||
|
this.autowiredType = autowiredType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject() throws BeansException {
|
||||||
|
if(autowiredType == AutowiredType.Type.PLUGIN) {
|
||||||
|
return pluginObjectProvider.getObject();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
} else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN) {
|
||||||
|
try {
|
||||||
|
return pluginObjectProvider.getObject();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if (dependencyObj != null) {
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
return pluginObjectProvider.getObject();
|
||||||
|
}
|
||||||
|
throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(final Object... args) throws BeansException {
|
||||||
|
if(autowiredType == AutowiredType.Type.PLUGIN){
|
||||||
|
return pluginObjectProvider.getObject(args);
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
} else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){
|
||||||
|
try {
|
||||||
|
return pluginObjectProvider.getObject();
|
||||||
|
} catch (Exception e){
|
||||||
|
try {
|
||||||
|
return applicationContext.getSpringBeanFactory().getBean(requestingBeanName, args);
|
||||||
|
} catch (Exception e2){
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
return pluginObjectProvider.getObject(args);
|
||||||
|
}
|
||||||
|
throw new NoSuchBeanDefinitionException(this.descriptor.getResolvableType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Object getIfAvailable() throws BeansException {
|
||||||
|
if(autowiredType == AutowiredType.Type.PLUGIN){
|
||||||
|
return pluginObjectProvider.getIfAvailable();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN){
|
||||||
|
return resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
} else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){
|
||||||
|
Object dependencyObj = pluginObjectProvider.getIfAvailable();
|
||||||
|
if(dependencyObj == null){
|
||||||
|
dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
}
|
||||||
|
return dependencyObj;
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
return pluginObjectProvider.getIfAvailable();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ifAvailable(Consumer<Object> dependencyConsumer) throws BeansException {
|
||||||
|
Object ifAvailable = getIfAvailable();
|
||||||
|
if(ifAvailable != null){
|
||||||
|
dependencyConsumer.accept(ifAvailable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Object getIfUnique() throws BeansException {
|
||||||
|
if(autowiredType == AutowiredType.Type.PLUGIN){
|
||||||
|
return pluginObjectProvider.getIfUnique();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN){
|
||||||
|
return resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
} else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){
|
||||||
|
Object dependencyObj = pluginObjectProvider.getIfUnique();
|
||||||
|
if(dependencyObj == null){
|
||||||
|
dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
}
|
||||||
|
return dependencyObj;
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){
|
||||||
|
Object dependencyObj = resolveDependencyFromMain(requestingBeanName, descriptor);
|
||||||
|
if(dependencyObj != null){
|
||||||
|
return dependencyObj;
|
||||||
|
}
|
||||||
|
return pluginObjectProvider.getIfUnique();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ifUnique(Consumer<Object> dependencyConsumer) throws BeansException {
|
||||||
|
Object ifUnique = getIfUnique();
|
||||||
|
if(ifUnique != null){
|
||||||
|
dependencyConsumer.accept(ifUnique);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<Object> stream() {
|
||||||
|
if(autowiredType == AutowiredType.Type.PLUGIN){
|
||||||
|
return pluginObjectProvider.stream();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN){
|
||||||
|
return getStreamOfMain().stream();
|
||||||
|
} else if (autowiredType == AutowiredType.Type.PLUGIN_MAIN){
|
||||||
|
Stream<Object> stream = pluginObjectProvider.stream();
|
||||||
|
List<Object> collect = stream.collect(Collectors.toList());
|
||||||
|
if(!collect.isEmpty()){
|
||||||
|
return collect.stream();
|
||||||
|
}
|
||||||
|
return getStreamOfMain().stream();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){
|
||||||
|
Set<Object> collection = getStreamOfMain();
|
||||||
|
if(!collection.isEmpty()){
|
||||||
|
return collection.stream();
|
||||||
|
}
|
||||||
|
return pluginObjectProvider.stream();
|
||||||
|
}
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<Object> orderedStream() {
|
||||||
|
if(autowiredType == AutowiredType.Type.PLUGIN){
|
||||||
|
return pluginObjectProvider.orderedStream();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN){
|
||||||
|
return getStreamOfMain().stream().sorted();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.PLUGIN_MAIN){
|
||||||
|
Stream<Object> stream = pluginObjectProvider.stream();
|
||||||
|
List<Object> collect = stream.collect(Collectors.toList());
|
||||||
|
if(!collect.isEmpty()){
|
||||||
|
return collect.stream();
|
||||||
|
}
|
||||||
|
return getStreamOfMain().stream().sorted();
|
||||||
|
} else if(autowiredType == AutowiredType.Type.MAIN_PLUGIN){
|
||||||
|
Set<Object> collection = getStreamOfMain();
|
||||||
|
if(!collection.isEmpty()){
|
||||||
|
return collection.stream().sorted();
|
||||||
|
}
|
||||||
|
return pluginObjectProvider.stream();
|
||||||
|
}
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Set<Object> getStreamOfMain(){
|
||||||
|
SpringBeanFactory springBeanFactory = applicationContext.getSpringBeanFactory();
|
||||||
|
Map<String, ?> beansOfType = springBeanFactory.getBeansOfType(descriptor.getDependencyType());
|
||||||
|
return new HashSet<>(beansOfType.values());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class NestedDependencyDescriptor extends DependencyDescriptor {
|
||||||
|
|
||||||
|
public NestedDependencyDescriptor(DependencyDescriptor original) {
|
||||||
|
super(original);
|
||||||
|
increaseNestingLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.common.PackageStructure;
|
||||||
|
import com.gitee.starblues.core.DefaultPluginInsideInfo;
|
||||||
|
import com.gitee.starblues.core.PluginInsideInfo;
|
||||||
|
import com.gitee.starblues.core.descriptor.DevPluginDescriptorLoader;
|
||||||
|
import com.gitee.starblues.core.descriptor.InsidePluginDescriptor;
|
||||||
|
import com.gitee.starblues.core.descriptor.PluginDescriptorLoader;
|
||||||
|
import com.gitee.starblues.core.descriptor.decrypt.EmptyPluginDescriptorDecrypt;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.integration.AutoIntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.integration.IntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.extract.DefaultOpExtractFactory;
|
||||||
|
import com.gitee.starblues.spring.extract.OpExtractFactory;
|
||||||
|
import com.gitee.starblues.spring.invoke.DefaultInvokeSupperCache;
|
||||||
|
import com.gitee.starblues.spring.invoke.InvokeSupperCache;
|
||||||
|
import com.gitee.starblues.utils.FilesUtils;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件自己的Interactive
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public class PluginOneselfInteractive implements PluginInteractive {
|
||||||
|
|
||||||
|
private final PluginInsideInfo pluginInsideInfo;
|
||||||
|
private final MainApplicationContext mainApplicationContext;
|
||||||
|
private final IntegrationConfiguration configuration;
|
||||||
|
private final InvokeSupperCache invokeSupperCache;
|
||||||
|
private final OpExtractFactory opExtractFactory;
|
||||||
|
|
||||||
|
public PluginOneselfInteractive(){
|
||||||
|
this.pluginInsideInfo = createPluginInsideInfo();
|
||||||
|
this.mainApplicationContext = new EmptyMainApplicationContext();
|
||||||
|
this.configuration = new AutoIntegrationConfiguration();
|
||||||
|
this.invokeSupperCache = new DefaultInvokeSupperCache();
|
||||||
|
this.opExtractFactory = new DefaultOpExtractFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsidePluginDescriptor getPluginDescriptor() {
|
||||||
|
return pluginInsideInfo.getPluginDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginInsideInfo getPluginInsideInfo() {
|
||||||
|
return pluginInsideInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MainApplicationContext getMainApplicationContext() {
|
||||||
|
return mainApplicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntegrationConfiguration getConfiguration() {
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InvokeSupperCache getInvokeSupperCache() {
|
||||||
|
return invokeSupperCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OpExtractFactory getOpExtractFactory() {
|
||||||
|
return opExtractFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PluginInsideInfo createPluginInsideInfo(){
|
||||||
|
EmptyPluginDescriptorDecrypt descriptorDecrypt = new EmptyPluginDescriptorDecrypt();
|
||||||
|
try (PluginDescriptorLoader pluginDescriptorLoader = new DevPluginDescriptorLoader(descriptorDecrypt)){
|
||||||
|
Path classesPath = Paths.get(this.getClass().getResource("/").toURI()).getParent();
|
||||||
|
String metaInf = FilesUtils.joiningFilePath(classesPath.toString(), PackageStructure.META_INF_NAME);
|
||||||
|
InsidePluginDescriptor pluginDescriptor = pluginDescriptorLoader.load(Paths.get(metaInf));
|
||||||
|
if(pluginDescriptor == null){
|
||||||
|
throw new RuntimeException("没有发现插件信息, 请使用框架提供的Maven插件器对插件进行编译!");
|
||||||
|
}
|
||||||
|
return new DefaultPluginInsideInfo(pluginDescriptor);
|
||||||
|
} catch (Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.oneself.ConfigureMainPluginEnvironment;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件自主启动的 SpringApplication
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @version 3.1.0
|
||||||
|
* @since 3.0.4
|
||||||
|
*/
|
||||||
|
public class PluginOneselfSpringApplication extends SpringApplication {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(PluginSpringApplication.class);
|
||||||
|
|
||||||
|
protected final SpringPluginProcessor pluginProcessor;
|
||||||
|
protected final ProcessorContext processorContext;
|
||||||
|
|
||||||
|
private final ConfigurePluginEnvironment configurePluginEnvironment;
|
||||||
|
private final GenericApplicationContext applicationContext;
|
||||||
|
|
||||||
|
|
||||||
|
public PluginOneselfSpringApplication(SpringPluginProcessor pluginProcessor,
|
||||||
|
ProcessorContext processorContext,
|
||||||
|
Class<?>... primarySources) {
|
||||||
|
super(primarySources);
|
||||||
|
this.pluginProcessor = pluginProcessor;
|
||||||
|
this.processorContext = processorContext;
|
||||||
|
this.configurePluginEnvironment = new ConfigurePluginEnvironment(processorContext);
|
||||||
|
this.applicationContext = getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GenericApplicationContext getApplicationContext() {
|
||||||
|
return (GenericApplicationContext) super.createApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
|
||||||
|
super.configureEnvironment(environment, args);
|
||||||
|
configurePluginEnvironment.configureEnvironment(environment, args);
|
||||||
|
new ConfigureMainPluginEnvironment(processorContext).configureEnvironment(environment, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
|
||||||
|
super.bindToSpringApplication(environment);
|
||||||
|
configurePluginEnvironment.logProfiles(environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ConfigurableApplicationContext createApplicationContext() {
|
||||||
|
return this.applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigurableApplicationContext run(String... args) {
|
||||||
|
try {
|
||||||
|
processorContext.setApplicationContext(this.applicationContext);
|
||||||
|
PluginContextHolder.initialize(processorContext);
|
||||||
|
pluginProcessor.initialize(processorContext);
|
||||||
|
return super.run(args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
pluginProcessor.failure(processorContext);
|
||||||
|
logger.debug("启动插件[{}]失败. {}",
|
||||||
|
processorContext.getPluginDescriptor().getPluginId(),
|
||||||
|
e.getMessage(), e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refresh(ConfigurableApplicationContext applicationContext) {
|
||||||
|
pluginProcessor.refreshBefore(processorContext);
|
||||||
|
super.refresh(applicationContext);
|
||||||
|
pluginProcessor.refreshAfter(processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.boot.Banner;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.WebApplicationType;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件SpringApplication实现
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public class PluginSpringApplication extends SpringApplication {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(PluginSpringApplication.class);
|
||||||
|
|
||||||
|
protected final SpringPluginProcessor pluginProcessor;
|
||||||
|
protected final ProcessorContext processorContext;
|
||||||
|
|
||||||
|
private final ConfigurePluginEnvironment configurePluginEnvironment;
|
||||||
|
private final GenericApplicationContext applicationContext;
|
||||||
|
private final ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
|
||||||
|
public PluginSpringApplication(SpringPluginProcessor pluginProcessor,
|
||||||
|
ProcessorContext processorContext,
|
||||||
|
Class<?>... primarySources) {
|
||||||
|
super(primarySources);
|
||||||
|
this.pluginProcessor = pluginProcessor;
|
||||||
|
this.processorContext = processorContext;
|
||||||
|
this.resourceLoader = processorContext.getResourceLoader();
|
||||||
|
this.configurePluginEnvironment = new ConfigurePluginEnvironment(processorContext);
|
||||||
|
this.applicationContext = getApplicationContext();
|
||||||
|
setDefaultPluginConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GenericApplicationContext getApplicationContext(){
|
||||||
|
DefaultListableBeanFactory beanFactory = getBeanFactory(processorContext);
|
||||||
|
if(processorContext.getMainApplicationContext().isWebEnvironment()){
|
||||||
|
return new PluginWebApplicationContext(beanFactory, processorContext);
|
||||||
|
} else {
|
||||||
|
return new PluginApplicationContext(beanFactory, processorContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DefaultListableBeanFactory getBeanFactory(ProcessorContext processorContext){
|
||||||
|
return new PluginListableBeanFactory(processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultPluginConfig(){
|
||||||
|
setResourceLoader(resourceLoader);
|
||||||
|
setBannerMode(Banner.Mode.OFF);
|
||||||
|
setEnvironment(new StandardEnvironment());
|
||||||
|
setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
setRegisterShutdownHook(false);
|
||||||
|
setLogStartupInfo(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
|
||||||
|
super.configureEnvironment(environment, args);
|
||||||
|
configurePluginEnvironment.configureEnvironment(environment, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
|
||||||
|
super.bindToSpringApplication(environment);
|
||||||
|
configurePluginEnvironment.logProfiles(environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ConfigurableApplicationContext createApplicationContext() {
|
||||||
|
return this.applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigurableApplicationContext run(String... args) {
|
||||||
|
try {
|
||||||
|
processorContext.setApplicationContext(this.applicationContext);
|
||||||
|
PluginContextHolder.initialize(processorContext);
|
||||||
|
pluginProcessor.initialize(processorContext);
|
||||||
|
return super.run(args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
pluginProcessor.failure(processorContext);
|
||||||
|
logger.debug("启动插件[{}]失败. {}",
|
||||||
|
processorContext.getPluginDescriptor().getPluginId(),
|
||||||
|
e.getMessage(), e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refresh(ConfigurableApplicationContext applicationContext) {
|
||||||
|
pluginProcessor.refreshBefore(processorContext);
|
||||||
|
super.refresh(applicationContext);
|
||||||
|
pluginProcessor.refreshAfter(processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.listener.PluginApplicationWebEventListener;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.spring.environment.EnvironmentProvider;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.boot.web.context.WebServerApplicationContext;
|
||||||
|
import org.springframework.boot.web.server.WebServer;
|
||||||
|
import org.springframework.boot.web.server.WebServerException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主程序为 web 类型时创建的插件 ApplicationContext
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public class PluginWebApplicationContext extends PluginApplicationContext implements WebServerApplicationContext {
|
||||||
|
|
||||||
|
private final WebServer webServer;
|
||||||
|
private final String serverNamespace;
|
||||||
|
|
||||||
|
public PluginWebApplicationContext(DefaultListableBeanFactory beanFactory, ProcessorContext processorContext) {
|
||||||
|
super(beanFactory, processorContext);
|
||||||
|
this.webServer = new PluginSimulationWebServer(processorContext);
|
||||||
|
this.serverNamespace = processorContext.getPluginDescriptor().getPluginId();
|
||||||
|
addApplicationListener(new PluginApplicationWebEventListener(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebServer getWebServer() {
|
||||||
|
return webServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getServerNamespace() {
|
||||||
|
return serverNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class PluginSimulationWebServer implements WebServer {
|
||||||
|
|
||||||
|
private final int port;
|
||||||
|
|
||||||
|
public PluginSimulationWebServer(ProcessorContext processorContext) {
|
||||||
|
EnvironmentProvider provider = processorContext.getMainApplicationContext().getEnvironmentProvider();
|
||||||
|
Integer port = provider.getInteger("server.port");
|
||||||
|
if(port == null){
|
||||||
|
this.port = -1;
|
||||||
|
} else {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() throws WebServerException {
|
||||||
|
throw new InvalidWebServerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() throws WebServerException {
|
||||||
|
throw new InvalidWebServerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InvalidWebServerException extends WebServerException{
|
||||||
|
|
||||||
|
public InvalidWebServerException() {
|
||||||
|
super("Invalid operation", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve config HttpMessageConverters bean
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public class ResolveHttpMessageConvertersConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||||
|
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.coexist.CoexistAllowAutoConfiguration;
|
||||||
|
import com.gitee.starblues.bootstrap.launcher.*;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.realize.AutowiredTypeDefiner;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.spring.SpringPluginHook;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件引导抽象类。插件入口需集成本抽象类
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public abstract class SpringPluginBootstrap {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private ProcessorContext.RunMode runMode = ProcessorContext.RunMode.ONESELF;
|
||||||
|
@Getter
|
||||||
|
private volatile PluginInteractive pluginInteractive;
|
||||||
|
@Getter
|
||||||
|
private final List<SpringPluginProcessor> customPluginProcessors = new ArrayList<>();
|
||||||
|
@Getter
|
||||||
|
private final CoexistAllowAutoConfiguration coexistAllowAutoConfiguration = new CoexistAllowAutoConfiguration();
|
||||||
|
|
||||||
|
private final BootstrapLauncherFactory launcherFactory = new DefaultBootstrapLauncherFactory();
|
||||||
|
|
||||||
|
public SpringPluginBootstrap() {
|
||||||
|
SpringPluginBootstrapBinder.set(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final SpringPluginHook run(String[] args){
|
||||||
|
return run(this.getClass(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final SpringPluginHook run(Class<?> primarySources, String[] args){
|
||||||
|
return run(new Class[]{ primarySources }, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final SpringPluginHook run(Class<?>[] primarySources, String[] args){
|
||||||
|
return start(primarySources, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpringPluginHook start(Class<?>[] primarySources, String[] args){
|
||||||
|
configCoexistAllowAutoConfiguration(this.coexistAllowAutoConfiguration);
|
||||||
|
createPluginInteractive();
|
||||||
|
addCustomSpringPluginProcessor();
|
||||||
|
BootstrapLauncher bootstrapLauncher = launcherFactory.create(this);
|
||||||
|
return bootstrapLauncher.launch(primarySources, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final SpringPluginBootstrap setPluginInteractive(PluginInteractive pluginInteractive) {
|
||||||
|
this.pluginInteractive = pluginInteractive;
|
||||||
|
this.runMode = ProcessorContext.RunMode.PLUGIN;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final SpringPluginBootstrap addSpringPluginProcessor(SpringPluginProcessor springPluginProcessor){
|
||||||
|
if(springPluginProcessor != null){
|
||||||
|
customPluginProcessors.add(springPluginProcessor);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void createPluginInteractive(){
|
||||||
|
if(pluginInteractive != null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
createPluginInteractiveOfOneself();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void createPluginInteractiveOfOneself(){
|
||||||
|
this.pluginInteractive = new PluginOneselfInteractive();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子类自定义插件 SpringPluginProcessor
|
||||||
|
*/
|
||||||
|
protected void addCustomSpringPluginProcessor(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 AutowiredTypeDefiner
|
||||||
|
* @return AutowiredTypeDefiner
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
protected AutowiredTypeDefiner autowiredTypeDefiner(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在 Coexist 模式下手动配置 spring-boot-auto-configuration 类
|
||||||
|
* @param configuration 配置的类
|
||||||
|
*/
|
||||||
|
protected void configCoexistAllowAutoConfiguration(CoexistAllowAutoConfiguration configuration){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.gitee.starblues.bootstrap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SpringPluginBootstrap 实例绑者
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public class SpringPluginBootstrapBinder {
|
||||||
|
|
||||||
|
private final static ThreadLocal<SpringPluginBootstrap> BINDER = new ThreadLocal<>();
|
||||||
|
|
||||||
|
|
||||||
|
public static SpringPluginBootstrap get(){
|
||||||
|
return BINDER.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void set(SpringPluginBootstrap bootstrap){
|
||||||
|
BINDER.set(bootstrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void remove(){
|
||||||
|
BINDER.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.gitee.starblues.bootstrap.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入类型
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface AutowiredType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件Bean注入类型
|
||||||
|
* @return Type
|
||||||
|
*/
|
||||||
|
Type value() default Type.PLUGIN;
|
||||||
|
|
||||||
|
|
||||||
|
enum Type{
|
||||||
|
/**
|
||||||
|
* Bean 注入类型: 仅插件(默认)
|
||||||
|
*/
|
||||||
|
PLUGIN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean 注入类型: 仅主程序
|
||||||
|
*/
|
||||||
|
MAIN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean 注入类型: 先插件后主程序
|
||||||
|
*/
|
||||||
|
PLUGIN_MAIN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean 注入类型: 先主程序后插件
|
||||||
|
*/
|
||||||
|
MAIN_PLUGIN
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁用web环境. 如果该注解加入到入口类上, 表示当前插件禁用web的功能。
|
||||||
|
* 包括:controller注册、拦截器注册、web静态资源访问、thymeleaf模板引擎
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface DisablePluginWeb {
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件自主运行配置
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface OneselfConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主程序配置文件名称
|
||||||
|
* @return String[]
|
||||||
|
*/
|
||||||
|
String[] mainConfigFileName() default {};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解决方法级别调用时, 当前线程非本插件的ClassLoader注解
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface ResolveClassLoader {
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.coexist;
|
||||||
|
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coexist模式下存储当前插件允许的 auto 配置
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public class CoexistAllowAutoConfiguration {
|
||||||
|
|
||||||
|
private final Set<String> allowPrefix = new HashSet<>();
|
||||||
|
|
||||||
|
public CoexistAllowAutoConfiguration(){
|
||||||
|
addDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDefault(){
|
||||||
|
allowPrefix.add("org.springframework.boot.autoconfigure.aop.AopAutoConfiguration");
|
||||||
|
}
|
||||||
|
|
||||||
|
public CoexistAllowAutoConfiguration add(String autoConfigurationClass){
|
||||||
|
if(ObjectUtils.isEmpty(autoConfigurationClass)){
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
allowPrefix.add(autoConfigurationClass);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean match(String autoConfigurationClass){
|
||||||
|
for (String prefix : allowPrefix) {
|
||||||
|
if(autoConfigurationClass.startsWith(prefix)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.coexist;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.ResolveClassLoader;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coexist模式下解决调用方法时, 非本插件的ClassLoader
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
public class CoexistResolveClassLoaderAspect {
|
||||||
|
|
||||||
|
@Pointcut("@annotation(com.gitee.starblues.bootstrap.annotation.ResolveClassLoader)")
|
||||||
|
public void test() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("@annotation(resolveClassLoader)")
|
||||||
|
public Object around(ProceedingJoinPoint pjp, ResolveClassLoader resolveClassLoader) throws Throwable{
|
||||||
|
Thread thread = Thread.currentThread();
|
||||||
|
ClassLoader oldClassLoader = thread.getContextClassLoader();
|
||||||
|
try {
|
||||||
|
Object target = pjp.getTarget();
|
||||||
|
thread.setContextClassLoader(target.getClass().getClassLoader());
|
||||||
|
return pjp.proceed();
|
||||||
|
} finally {
|
||||||
|
thread.setContextClassLoader(oldClassLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.launcher;
|
||||||
|
|
||||||
|
import com.gitee.starblues.spring.SpringPluginHook;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件启动器
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public interface BootstrapLauncher {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动插件
|
||||||
|
* @param primarySources 主启动类
|
||||||
|
* @param args 启动参数
|
||||||
|
* @return SpringPluginHook
|
||||||
|
*/
|
||||||
|
SpringPluginHook launch(Class<?>[] primarySources, String[] args);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.launcher;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BootstrapLauncher 创造工厂
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public interface BootstrapLauncherFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创造 BootstrapLauncher
|
||||||
|
* @param bootstrap SpringPluginBootstrap
|
||||||
|
* @return BootstrapLauncher
|
||||||
|
*/
|
||||||
|
BootstrapLauncher create(SpringPluginBootstrap bootstrap);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.launcher;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.*;
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
|
||||||
|
import com.gitee.starblues.bootstrap.coexist.CoexistResolveClassLoaderAspect;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.DefaultProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.spring.SpringPluginHook;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coexist 类型启动器
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
* @see com.gitee.starblues.loader.DevelopmentMode#COEXIST
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CoexistBootstrapLauncher implements BootstrapLauncher{
|
||||||
|
|
||||||
|
private final SpringPluginBootstrap bootstrap;
|
||||||
|
private final SpringPluginProcessor pluginProcessor;
|
||||||
|
private final PluginInteractive pluginInteractive;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpringPluginHook launch(Class<?>[] primarySources, String[] args) {
|
||||||
|
ProcessorContext processorContext = new DefaultProcessorContext(
|
||||||
|
bootstrap.getRunMode(), bootstrap, pluginInteractive, bootstrap.getClass()
|
||||||
|
);
|
||||||
|
SpringApplication springApplication = new CoexistSpringApplication(
|
||||||
|
pluginProcessor,
|
||||||
|
processorContext,
|
||||||
|
primarySources);
|
||||||
|
springApplication.run(args);
|
||||||
|
return new DefaultSpringPluginHook(pluginProcessor, processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CoexistSpringApplication extends PluginSpringApplication{
|
||||||
|
|
||||||
|
public CoexistSpringApplication(SpringPluginProcessor pluginProcessor, ProcessorContext processorContext, Class<?>... primarySources) {
|
||||||
|
super(pluginProcessor, processorContext, primarySources);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DefaultListableBeanFactory getBeanFactory(ProcessorContext processorContext) {
|
||||||
|
return new CoexistPluginListableBeanFactory(processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
|
||||||
|
super.configureEnvironment(environment, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GenericApplicationContext getApplicationContext() {
|
||||||
|
PluginApplicationContext applicationContext = (PluginApplicationContext) super.getApplicationContext();
|
||||||
|
applicationContext.register(CoexistResolveClassLoaderAspect.class);
|
||||||
|
return applicationContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CoexistPluginListableBeanFactory extends PluginListableBeanFactory{
|
||||||
|
|
||||||
|
public CoexistPluginListableBeanFactory(ProcessorContext processorContext) {
|
||||||
|
super(processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AutowiredTypeResolver getAutowiredTypeResolver(ProcessorContext processorContext) {
|
||||||
|
return new CoexistAutowiredTypeResolver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CoexistAutowiredTypeResolver implements AutowiredTypeResolver{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AutowiredType.Type resolve(DependencyDescriptor descriptor) {
|
||||||
|
AutowiredType autowiredType = descriptor.getAnnotation(AutowiredType.class);
|
||||||
|
if(autowiredType != null){
|
||||||
|
return autowiredType.value();
|
||||||
|
} else {
|
||||||
|
return AutowiredType.Type.PLUGIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.launcher;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.PluginDisableAutoConfiguration;
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ComposeSpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.loader.launcher.DevelopmentModeSetting;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认的 BootstrapLauncher 创造工厂
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public class DefaultBootstrapLauncherFactory implements BootstrapLauncherFactory{
|
||||||
|
@Override
|
||||||
|
public BootstrapLauncher create(SpringPluginBootstrap bootstrap) {
|
||||||
|
PluginDisableAutoConfiguration.setLaunchPlugin();
|
||||||
|
ProcessorContext.RunMode runMode = bootstrap.getRunMode();
|
||||||
|
List<SpringPluginProcessor> customPluginProcessors = bootstrap.getCustomPluginProcessors();
|
||||||
|
PluginInteractive pluginInteractive = bootstrap.getPluginInteractive();
|
||||||
|
|
||||||
|
SpringPluginProcessor pluginProcessor = new ComposeSpringPluginProcessor(runMode, customPluginProcessors);
|
||||||
|
BootstrapLauncher bootstrapLauncher = null;
|
||||||
|
if(DevelopmentModeSetting.isolation()){
|
||||||
|
bootstrapLauncher = new IsolationBootstrapLauncher(bootstrap, pluginProcessor, pluginInteractive);
|
||||||
|
} else if(DevelopmentModeSetting.coexist()){
|
||||||
|
bootstrapLauncher = new CoexistBootstrapLauncher(bootstrap, pluginProcessor, pluginInteractive);
|
||||||
|
} else {
|
||||||
|
bootstrapLauncher = new OneselfBootstrapLauncher(bootstrap, pluginProcessor, pluginInteractive);
|
||||||
|
}
|
||||||
|
return bootstrapLauncher;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.launcher;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.DefaultSpringPluginHook;
|
||||||
|
import com.gitee.starblues.bootstrap.PluginSpringApplication;
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.DefaultProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.spring.SpringPluginHook;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isolation 模式插件启动器
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.4
|
||||||
|
* @version 3.1.0
|
||||||
|
* @see com.gitee.starblues.loader.DevelopmentMode#ISOLATION
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class IsolationBootstrapLauncher implements BootstrapLauncher{
|
||||||
|
|
||||||
|
private final SpringPluginBootstrap bootstrap;
|
||||||
|
private final SpringPluginProcessor pluginProcessor;
|
||||||
|
private final PluginInteractive pluginInteractive;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpringPluginHook launch(Class<?>[] primarySources, String[] args) {
|
||||||
|
ProcessorContext.RunMode runMode = bootstrap.getRunMode();
|
||||||
|
|
||||||
|
ProcessorContext processorContext = new DefaultProcessorContext(
|
||||||
|
runMode, bootstrap, pluginInteractive, bootstrap.getClass()
|
||||||
|
);
|
||||||
|
SpringApplication springApplication = new PluginSpringApplication(
|
||||||
|
pluginProcessor,
|
||||||
|
processorContext,
|
||||||
|
primarySources);
|
||||||
|
springApplication.run(args);
|
||||||
|
return new DefaultSpringPluginHook(pluginProcessor, processorContext);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.gitee.starblues.bootstrap.launcher;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.DefaultSpringPluginHook;
|
||||||
|
import com.gitee.starblues.bootstrap.PluginOneselfSpringApplication;
|
||||||
|
import com.gitee.starblues.bootstrap.PluginSpringApplication;
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.DefaultProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.spring.SpringPluginHook;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件自主启动配置
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @version 3.1.0
|
||||||
|
* @since 3.0.4
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class OneselfBootstrapLauncher implements BootstrapLauncher{
|
||||||
|
|
||||||
|
private final SpringPluginBootstrap bootstrap;
|
||||||
|
private final SpringPluginProcessor pluginProcessor;
|
||||||
|
private final PluginInteractive pluginInteractive;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpringPluginHook launch(Class<?>[] primarySources, String[] args) {
|
||||||
|
ProcessorContext.RunMode runMode = bootstrap.getRunMode();
|
||||||
|
|
||||||
|
ProcessorContext processorContext = new DefaultProcessorContext(
|
||||||
|
runMode, bootstrap, pluginInteractive, bootstrap.getClass()
|
||||||
|
);
|
||||||
|
SpringApplication springApplication = new PluginOneselfSpringApplication(
|
||||||
|
pluginProcessor,
|
||||||
|
processorContext,
|
||||||
|
primarySources);
|
||||||
|
springApplication.run(args);
|
||||||
|
return new DefaultSpringPluginHook(pluginProcessor, processorContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.listener;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.PluginWebApplicationContext;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.boot.web.context.WebServerApplicationContext;
|
||||||
|
import org.springframework.boot.web.context.WebServerInitializedEvent;
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.core.ResolvableType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件监听器扩展
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public class PluginApplicationWebEventListener implements ApplicationListener<ApplicationEvent> {
|
||||||
|
|
||||||
|
|
||||||
|
private final PluginWebApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public PluginApplicationWebEventListener(PluginWebApplicationContext applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ApplicationEvent event) {
|
||||||
|
if (event instanceof ApplicationReadyEvent) {
|
||||||
|
callWebServerInitializedEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
protected void callWebServerInitializedEvent(){
|
||||||
|
String[] beanNamesForType = applicationContext.getBeanNamesForType(ResolvableType.forClassWithGenerics(
|
||||||
|
ApplicationListener.class, WebServerInitializedEvent.class
|
||||||
|
));
|
||||||
|
PluginWebServerInitializedEvent pluginWebServerInitializedEvent =
|
||||||
|
new PluginWebServerInitializedEvent(applicationContext);
|
||||||
|
for (String beanName : beanNamesForType) {
|
||||||
|
try {
|
||||||
|
ApplicationListener<WebServerInitializedEvent> applicationListener =
|
||||||
|
(ApplicationListener<WebServerInitializedEvent>) applicationContext.getBean(beanName);
|
||||||
|
applicationListener.onApplicationEvent(pluginWebServerInitializedEvent);
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PluginWebServerInitializedEvent extends WebServerInitializedEvent{
|
||||||
|
|
||||||
|
private final PluginWebApplicationContext pluginWebApplicationContext;
|
||||||
|
|
||||||
|
protected PluginWebServerInitializedEvent(PluginWebApplicationContext pluginWebApplicationContext) {
|
||||||
|
super(pluginWebApplicationContext.getWebServer());
|
||||||
|
this.pluginWebApplicationContext = pluginWebApplicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebServerApplicationContext getApplicationContext() {
|
||||||
|
return pluginWebApplicationContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,202 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.DisablePluginWeb;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.oneself.OneselfProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.web.PluginControllerProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.web.PluginInterceptorsProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.web.PluginStaticResourceProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.AnnotationUtils;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.utils.OrderUtils;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import com.gitee.starblues.utils.OrderPriority;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组合的处理器
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.1
|
||||||
|
*/
|
||||||
|
public class ComposeSpringPluginProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
private final ProcessorContext.RunMode runMode;
|
||||||
|
|
||||||
|
private List<SpringPluginProcessor> processors;
|
||||||
|
|
||||||
|
public ComposeSpringPluginProcessor(ProcessorContext.RunMode runMode) {
|
||||||
|
this(runMode, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComposeSpringPluginProcessor(ProcessorContext.RunMode runMode, List<SpringPluginProcessor> processors) {
|
||||||
|
this.runMode = runMode;
|
||||||
|
if(!ObjectUtils.isEmpty(processors)){
|
||||||
|
this.processors = processors;
|
||||||
|
} else {
|
||||||
|
this.processors = new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSpringPluginProcessor(SpringPluginProcessor springPluginProcessor){
|
||||||
|
if(springPluginProcessor != null){
|
||||||
|
this.processors.add(springPluginProcessor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ProcessorContext context) throws ProcessorException {
|
||||||
|
List<SpringPluginProcessor> processors = new ArrayList<>();
|
||||||
|
addDefaultProcessors(context, processors);
|
||||||
|
addDefaultWebEnvProcessors(context, processors);
|
||||||
|
addOneselfProcessors(context, processors);
|
||||||
|
processors.addAll(this.processors);
|
||||||
|
this.processors = processors.stream()
|
||||||
|
.filter(p->{
|
||||||
|
ProcessorContext.RunMode runMode = p.runMode();
|
||||||
|
return runMode == ProcessorContext.RunMode.ALL || runMode == this.runMode;
|
||||||
|
})
|
||||||
|
.sorted(OrderUtils.orderPriority(SpringPluginProcessor::order))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
for (SpringPluginProcessor processor : this.processors) {
|
||||||
|
try {
|
||||||
|
processor.initialize(context);
|
||||||
|
} catch (Throwable e){
|
||||||
|
processException(processor, "initialize", e, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshBefore(ProcessorContext context) throws ProcessorException {
|
||||||
|
for (SpringPluginProcessor processor : processors) {
|
||||||
|
try {
|
||||||
|
processor.refreshBefore(context);
|
||||||
|
} catch (Throwable e){
|
||||||
|
processException(processor, "refreshBefore", e, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshAfter(ProcessorContext context) throws ProcessorException {
|
||||||
|
for (SpringPluginProcessor processor : processors) {
|
||||||
|
try {
|
||||||
|
processor.refreshAfter(context);
|
||||||
|
} catch (Throwable e){
|
||||||
|
processException(processor, "refreshAfter", e, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void failure(ProcessorContext context) throws ProcessorException {
|
||||||
|
for (SpringPluginProcessor processor : processors) {
|
||||||
|
try {
|
||||||
|
processor.failure(context);
|
||||||
|
} catch (Throwable e){
|
||||||
|
processException(processor, "failure", e, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(ProcessorContext context) throws ProcessorException {
|
||||||
|
for (SpringPluginProcessor processor : processors) {
|
||||||
|
try {
|
||||||
|
processor.close(context);
|
||||||
|
} catch (Throwable e){
|
||||||
|
processException(processor, "close", e, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OrderPriority order() {
|
||||||
|
return OrderPriority.getHighPriority();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取默认的处理者
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @param processors 处理者容器集合
|
||||||
|
*/
|
||||||
|
protected void addDefaultProcessors(ProcessorContext context, List<SpringPluginProcessor> processors){
|
||||||
|
processors.add(new FrameDefineBeanProcessor());
|
||||||
|
processors.add(new ExtractBeanProcessor());
|
||||||
|
processors.add(new InvokeOtherPluginProcessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加默认web环境处理者
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @param processors 处理者容器集合
|
||||||
|
*/
|
||||||
|
protected void addDefaultWebEnvProcessors(ProcessorContext context, List<SpringPluginProcessor> processors){
|
||||||
|
MainApplicationContext mainApplicationContext = context.getMainApplicationContext();
|
||||||
|
if(!mainApplicationContext.isWebEnvironment()){
|
||||||
|
// 主程序不是web类型, 则不进行注册
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SpringPluginBootstrap springPluginBootstrap = context.getSpringPluginBootstrap();
|
||||||
|
DisablePluginWeb disablePluginWeb = AnnotationUtils.findAnnotation(springPluginBootstrap.getClass(),
|
||||||
|
DisablePluginWeb.class);
|
||||||
|
if(disablePluginWeb != null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.getWebConfig().setEnable(true);
|
||||||
|
if(mainApplicationContext.isRegisterController()){
|
||||||
|
processors.add(new PluginControllerProcessor());
|
||||||
|
}
|
||||||
|
processors.add(new PluginInterceptorsProcessor());
|
||||||
|
processors.add(new PluginStaticResourceProcessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 Oneself 模式处理者
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @param processors 处理者容器集合
|
||||||
|
*/
|
||||||
|
private void addOneselfProcessors(ProcessorContext context, List<SpringPluginProcessor> processors) {
|
||||||
|
processors.add(new OneselfProcessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processException(SpringPluginProcessor processor, String executeType,
|
||||||
|
Throwable e, boolean isThrow) throws ProcessorException{
|
||||||
|
String error = "Processor[" + processor.getClass().getName() + "] execute[" + executeType + "] failure : "
|
||||||
|
+ e.getMessage();
|
||||||
|
logger.error(error, e);
|
||||||
|
if(isThrow){
|
||||||
|
throw new ProcessorException(error, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
import com.gitee.starblues.core.PluginInfo;
|
||||||
|
import com.gitee.starblues.core.descriptor.InsidePluginDescriptor;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.CacheRegistryInfo;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.integration.IntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.SpringBeanFactory;
|
||||||
|
import com.gitee.starblues.spring.WebConfig;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认的处理者上下文
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class DefaultProcessorContext extends CacheRegistryInfo implements ProcessorContext{
|
||||||
|
|
||||||
|
private final RunMode runMode;
|
||||||
|
|
||||||
|
private final SpringPluginBootstrap springPluginBootstrap;
|
||||||
|
private final PluginInteractive pluginInteractive;
|
||||||
|
private final Class<? extends SpringPluginBootstrap> runnerClass;
|
||||||
|
private final MainApplicationContext mainApplicationContext;
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
private final ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
private final IntegrationConfiguration configuration;
|
||||||
|
private final WebConfig webConfig;
|
||||||
|
|
||||||
|
private GenericApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public DefaultProcessorContext(RunMode runMode, SpringPluginBootstrap springPluginBootstrap,
|
||||||
|
PluginInteractive pluginInteractive, Class<? extends SpringPluginBootstrap> runnerClass) {
|
||||||
|
this.runMode = runMode;
|
||||||
|
this.springPluginBootstrap = springPluginBootstrap;
|
||||||
|
this.pluginInteractive = pluginInteractive;
|
||||||
|
this.runnerClass = runnerClass;
|
||||||
|
this.classLoader = getPluginClassLoader();
|
||||||
|
this.resourceLoader = new DefaultResourceLoader(this.classLoader);
|
||||||
|
this.mainApplicationContext = pluginInteractive.getMainApplicationContext();
|
||||||
|
this.configuration = pluginInteractive.getConfiguration();
|
||||||
|
this.webConfig = new WebConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RunMode runMode() {
|
||||||
|
return runMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpringPluginBootstrap getSpringPluginBootstrap() {
|
||||||
|
return springPluginBootstrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InsidePluginDescriptor getPluginDescriptor() {
|
||||||
|
return pluginInteractive.getPluginDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginInfo getPluginInfo() {
|
||||||
|
return pluginInteractive.getPluginInsideInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends SpringPluginBootstrap> getRunnerClass() {
|
||||||
|
return runnerClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginInteractive getPluginInteractive() {
|
||||||
|
return pluginInteractive;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MainApplicationContext getMainApplicationContext() {
|
||||||
|
return mainApplicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpringBeanFactory getMainBeanFactory() {
|
||||||
|
return mainApplicationContext.getSpringBeanFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntegrationConfiguration getConfiguration() {
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GenericApplicationContext getApplicationContext() {
|
||||||
|
if(applicationContext == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader getClassLoader() {
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLoader getResourceLoader() {
|
||||||
|
return resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebConfig getWebConfig() {
|
||||||
|
return webConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(GenericApplicationContext applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ClassLoader getPluginClassLoader(){
|
||||||
|
return ClassUtils.getDefaultClassLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
import com.gitee.starblues.annotation.Extract;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorException;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.spring.extract.OpExtractFactory;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract 扩展Bean注册处理者
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class ExtractBeanProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshAfter(ProcessorContext context) throws ProcessorException {
|
||||||
|
GenericApplicationContext applicationContext = context.getApplicationContext();
|
||||||
|
Map<String, Object> extractMap = applicationContext.getBeansWithAnnotation(Extract.class);
|
||||||
|
if(ObjectUtils.isEmpty(extractMap)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String pluginId = context.getPluginDescriptor().getPluginId();
|
||||||
|
OpExtractFactory opExtractFactory = context.getPluginInteractive().getOpExtractFactory();
|
||||||
|
for (Object extract : extractMap.values()) {
|
||||||
|
opExtractFactory.add(pluginId, extract);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(ProcessorContext context) throws ProcessorException {
|
||||||
|
OpExtractFactory opExtractFactory = context.getPluginInteractive().getOpExtractFactory();
|
||||||
|
String pluginId = context.getPluginDescriptor().getPluginId();
|
||||||
|
opExtractFactory.remove(pluginId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.ALL;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.gitee.starblues.core.descriptor.InsidePluginDescriptor;
|
||||||
|
import com.gitee.starblues.integration.AutoIntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.integration.ExtendPointConfiguration;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 框架内置bean注册
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class FrameDefineBeanProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshBefore(ProcessorContext context) throws ProcessorException {
|
||||||
|
GenericApplicationContext applicationContext = context.getApplicationContext();
|
||||||
|
InsidePluginDescriptor pluginDescriptor = context.getPluginDescriptor();
|
||||||
|
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
|
||||||
|
beanFactory.registerSingleton("pluginDescriptor", pluginDescriptor.toPluginDescriptor());
|
||||||
|
beanFactory.registerSingleton("pluginInfo", context.getPluginInfo());
|
||||||
|
beanFactory.registerSingleton("mainApplicationContext", context.getMainApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
import com.gitee.starblues.annotation.Caller;
|
||||||
|
import com.gitee.starblues.annotation.Supplier;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.invoke.InvokeBeanFactory;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.scanner.PluginClassPathBeanDefinitionScanner;
|
||||||
|
import com.gitee.starblues.spring.ApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.ApplicationContextProxy;
|
||||||
|
import com.gitee.starblues.spring.invoke.InvokeSupperCache;
|
||||||
|
import com.gitee.starblues.spring.invoke.SupperCache;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import com.gitee.starblues.utils.ScanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反射调用其他插件的处理者
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class InvokeOtherPluginProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshBefore(ProcessorContext context) throws ProcessorException {
|
||||||
|
InvokeCallerBeanDefinitionScanner scanner = new InvokeCallerBeanDefinitionScanner(context);
|
||||||
|
scanner.doScan(ScanUtils.getScanBasePackages(context.getRunnerClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshAfter(ProcessorContext context) throws ProcessorException {
|
||||||
|
GenericApplicationContext applicationContext = context.getApplicationContext();
|
||||||
|
Map<String, Object> supplierBeans = applicationContext.getBeansWithAnnotation(Supplier.class);
|
||||||
|
String pluginId = context.getPluginDescriptor().getPluginId();
|
||||||
|
ApplicationContext applicationContextReflection = new ApplicationContextProxy(applicationContext);
|
||||||
|
InvokeSupperCache invokeSupperCache = context.getPluginInteractive().getInvokeSupperCache();
|
||||||
|
supplierBeans.forEach((k,v)->{
|
||||||
|
Supplier supplier = AnnotationUtils.findAnnotation(v.getClass(), Supplier.class);
|
||||||
|
String supperKey = k;
|
||||||
|
if(supplier != null && !ObjectUtils.isEmpty(supplier.value())){
|
||||||
|
supperKey = supplier.value();
|
||||||
|
}
|
||||||
|
invokeSupperCache.add(pluginId, new SupperCache(supperKey, k, applicationContextReflection));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class InvokeCallerBeanDefinitionScanner extends PluginClassPathBeanDefinitionScanner {
|
||||||
|
|
||||||
|
private final ProcessorContext context;
|
||||||
|
|
||||||
|
public InvokeCallerBeanDefinitionScanner(ProcessorContext context) {
|
||||||
|
super(context, false);
|
||||||
|
setResourceLoader(context.getResourceLoader());
|
||||||
|
this.context = context;
|
||||||
|
addIncludeFilter(new AnnotationTypeFilter(Caller.class));
|
||||||
|
addExcludeFilter((metadataReader, metadataReaderFactory) -> {
|
||||||
|
String className = metadataReader.getClassMetadata().getClassName();
|
||||||
|
return className.endsWith("package-info");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
|
||||||
|
Set<BeanDefinitionHolder> holders = super.doScan(basePackages);
|
||||||
|
ClassLoader pluginClassLoader = context.getClassLoader();
|
||||||
|
InvokeSupperCache invokeSupperCache = context.getPluginInteractive().getInvokeSupperCache();
|
||||||
|
for (BeanDefinitionHolder holder : holders) {
|
||||||
|
AbstractBeanDefinition definition = (AbstractBeanDefinition) holder.getBeanDefinition();
|
||||||
|
try {
|
||||||
|
Class<?> aClass = pluginClassLoader.loadClass(definition.getBeanClassName());
|
||||||
|
Caller caller = AnnotationUtils.findAnnotation(aClass, Caller.class);
|
||||||
|
if(caller == null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 是调用方
|
||||||
|
definition.getPropertyValues().add("callerAnnotation", caller);
|
||||||
|
definition.getPropertyValues().add("callerInterface", aClass);
|
||||||
|
definition.getPropertyValues().add("invokeSupperCache", invokeSupperCache);
|
||||||
|
definition.setBeanClass(InvokeBeanFactory.class);
|
||||||
|
definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return holders;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
|
||||||
|
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
import com.gitee.starblues.core.PluginInfo;
|
||||||
|
import com.gitee.starblues.core.descriptor.InsidePluginDescriptor;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.PluginInteractive;
|
||||||
|
import com.gitee.starblues.core.launcher.plugin.RegistryInfo;
|
||||||
|
import com.gitee.starblues.integration.IntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.SpringBeanFactory;
|
||||||
|
import com.gitee.starblues.spring.WebConfig;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理者上下文
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public interface ProcessorContext extends RegistryInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前运行模式
|
||||||
|
* @return RunMode
|
||||||
|
*/
|
||||||
|
RunMode runMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到入口类对象-SpringPluginBootstrap
|
||||||
|
* @return SpringPluginBootstrap
|
||||||
|
*/
|
||||||
|
SpringPluginBootstrap getSpringPluginBootstrap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到插件信息 PluginDescriptor
|
||||||
|
* @return PluginDescriptor
|
||||||
|
*/
|
||||||
|
InsidePluginDescriptor getPluginDescriptor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到插件信息 PluginInfo
|
||||||
|
* @return PluginInfo
|
||||||
|
*/
|
||||||
|
PluginInfo getPluginInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到启动的class类
|
||||||
|
* @return Class
|
||||||
|
*/
|
||||||
|
Class<? extends SpringPluginBootstrap> getRunnerClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到 PluginInteractive
|
||||||
|
* @return PluginInteractive
|
||||||
|
*/
|
||||||
|
PluginInteractive getPluginInteractive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到主程序的 ApplicationContext
|
||||||
|
* @return MainApplicationContext
|
||||||
|
*/
|
||||||
|
MainApplicationContext getMainApplicationContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到主程序的 SpringBeanFactory
|
||||||
|
* @return SpringBeanFactory
|
||||||
|
*/
|
||||||
|
SpringBeanFactory getMainBeanFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到当前框架的集成配置
|
||||||
|
* @return IntegrationConfiguration
|
||||||
|
*/
|
||||||
|
IntegrationConfiguration getConfiguration();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到当前插件的 ApplicationContext
|
||||||
|
* @return GenericApplicationContext
|
||||||
|
*/
|
||||||
|
GenericApplicationContext getApplicationContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到当前插件的 ClassLoader
|
||||||
|
* @return ClassLoader
|
||||||
|
*/
|
||||||
|
ClassLoader getClassLoader();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到插件的资源loader
|
||||||
|
* @return ResourceLoader
|
||||||
|
*/
|
||||||
|
ResourceLoader getResourceLoader();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 WebConfig
|
||||||
|
* @return WebConfig
|
||||||
|
*/
|
||||||
|
WebConfig getWebConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set 当前插件的 ApplicationContext
|
||||||
|
* @param applicationContext GenericApplicationContext
|
||||||
|
*/
|
||||||
|
void setApplicationContext(GenericApplicationContext applicationContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行模式
|
||||||
|
*/
|
||||||
|
enum RunMode{
|
||||||
|
/**
|
||||||
|
* 全部运行
|
||||||
|
*/
|
||||||
|
ALL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件环境运行
|
||||||
|
*/
|
||||||
|
PLUGIN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件独立运行
|
||||||
|
*/
|
||||||
|
ONESELF
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理者异常
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class ProcessorException extends RuntimeException{
|
||||||
|
|
||||||
|
public ProcessorException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessorException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessorException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessorException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ProcessorException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor;
|
||||||
|
|
||||||
|
import com.gitee.starblues.utils.Order;
|
||||||
|
import com.gitee.starblues.utils.OrderPriority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spring plugin 处理器
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public interface SpringPluginProcessor extends Order {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化时
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @throws ProcessorException 处理异常
|
||||||
|
*/
|
||||||
|
default void initialize(ProcessorContext context) throws ProcessorException{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新上下文前
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @throws ProcessorException 处理异常
|
||||||
|
*/
|
||||||
|
default void refreshBefore(ProcessorContext context) throws ProcessorException{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新上下文后
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @throws ProcessorException 处理异常
|
||||||
|
*/
|
||||||
|
default void refreshAfter(ProcessorContext context) throws ProcessorException{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动失败
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @throws ProcessorException 处理异常
|
||||||
|
*/
|
||||||
|
default void failure(ProcessorContext context) throws ProcessorException{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭容器时
|
||||||
|
* @param context ProcessorContext
|
||||||
|
* @throws ProcessorException 处理异常
|
||||||
|
*/
|
||||||
|
default void close(ProcessorContext context) throws ProcessorException{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行顺序
|
||||||
|
* @return OrderPriority
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
default OrderPriority order(){
|
||||||
|
return OrderPriority.getLowPriority();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理器运行模式
|
||||||
|
* @return RunMode
|
||||||
|
*/
|
||||||
|
ProcessorContext.RunMode runMode();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.interceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件拦截器注册者
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public interface PluginInterceptorRegister {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截器注册者
|
||||||
|
* @param registry 注册对象
|
||||||
|
*/
|
||||||
|
void registry(PluginInterceptorRegistry registry);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.interceptor;
|
||||||
|
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import com.gitee.starblues.utils.UrlUtils;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.PathMatcher;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
|
||||||
|
import org.springframework.web.servlet.handler.MappedInterceptor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件拦截器注册的信息
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class PluginInterceptorRegistration {
|
||||||
|
|
||||||
|
private final HandlerInterceptor interceptor;
|
||||||
|
private final PluginInterceptorRegistry.Type type;
|
||||||
|
private final String pluginRestApiPrefix;
|
||||||
|
|
||||||
|
private final List<String> includePatterns = new ArrayList<>();
|
||||||
|
|
||||||
|
private final List<String> excludePatterns = new ArrayList<>();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private PathMatcher pathMatcher;
|
||||||
|
|
||||||
|
private int order = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an {@link InterceptorRegistration} instance.
|
||||||
|
*
|
||||||
|
* @param interceptor 拦截器
|
||||||
|
* @param type 类型
|
||||||
|
* @param pluginRestApiPrefix 接口前缀
|
||||||
|
*/
|
||||||
|
public PluginInterceptorRegistration(HandlerInterceptor interceptor,
|
||||||
|
PluginInterceptorRegistry.Type type,
|
||||||
|
String pluginRestApiPrefix) {
|
||||||
|
this.interceptor = interceptor;
|
||||||
|
this.type = type;
|
||||||
|
String apiPrefix = null;
|
||||||
|
if(pluginRestApiPrefix.startsWith("/")){
|
||||||
|
apiPrefix = pluginRestApiPrefix;
|
||||||
|
} else {
|
||||||
|
apiPrefix = "/" + pluginRestApiPrefix;
|
||||||
|
}
|
||||||
|
if(apiPrefix.endsWith("/")){
|
||||||
|
apiPrefix = apiPrefix.substring(0, apiPrefix.lastIndexOf("/"));
|
||||||
|
}
|
||||||
|
this.pluginRestApiPrefix = apiPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add URL patterns to which the registered interceptor should apply to.
|
||||||
|
* @param patterns patterns
|
||||||
|
* @return PluginInterceptorRegistration
|
||||||
|
*/
|
||||||
|
public PluginInterceptorRegistration addPathPatterns(String... patterns) {
|
||||||
|
if(type == PluginInterceptorRegistry.Type.GLOBAL){
|
||||||
|
this.includePatterns.addAll(Arrays.asList(patterns));
|
||||||
|
}
|
||||||
|
// 局部的
|
||||||
|
for (String pattern : patterns) {
|
||||||
|
if(ObjectUtils.isEmpty(pattern)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.includePatterns.add(UrlUtils.joiningUrlPath(pluginRestApiPrefix, pattern));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add URL patterns to which the registered interceptor should not apply to.
|
||||||
|
* @param patterns patterns
|
||||||
|
* @return PluginInterceptorRegistration
|
||||||
|
*/
|
||||||
|
public PluginInterceptorRegistration excludePathPatterns(String... patterns) {
|
||||||
|
if(type == PluginInterceptorRegistry.Type.GLOBAL){
|
||||||
|
this.excludePatterns.addAll(Arrays.asList(patterns));
|
||||||
|
}
|
||||||
|
for (String pattern : patterns) {
|
||||||
|
if(ObjectUtils.isEmpty(pattern)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.excludePatterns.add(UrlUtils.joiningUrlPath(pluginRestApiPrefix, pattern));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A PathMatcher implementation to use with this interceptor. This is an optional,
|
||||||
|
* advanced property required only if using custom PathMatcher implementations
|
||||||
|
* that support mapping metadata other than the Ant path patterns supported
|
||||||
|
* by default.
|
||||||
|
* @param pathMatcher pathMatcher
|
||||||
|
* @return PluginInterceptorRegistration
|
||||||
|
*/
|
||||||
|
public PluginInterceptorRegistration pathMatcher(PathMatcher pathMatcher) {
|
||||||
|
this.pathMatcher = pathMatcher;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify an order position to be used. Default is 0.
|
||||||
|
* @param order order
|
||||||
|
* @since 5.0
|
||||||
|
* @return PluginInterceptorRegistration
|
||||||
|
*/
|
||||||
|
public PluginInterceptorRegistration order(int order){
|
||||||
|
this.order = order;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the order position to be used.
|
||||||
|
* @since 5.0
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected int getOrder() {
|
||||||
|
return this.order;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the underlying interceptor. If URL patterns are provided, the returned
|
||||||
|
* type is {@link MappedInterceptor}; otherwise {@link HandlerInterceptor}.
|
||||||
|
* @return object 为 {@link MappedInterceptor} or {@link HandlerInterceptor}
|
||||||
|
*/
|
||||||
|
protected Object getInterceptor() {
|
||||||
|
if(type == PluginInterceptorRegistry.Type.PLUGIN){
|
||||||
|
if(this.includePatterns.isEmpty()){
|
||||||
|
this.includePatterns.add(UrlUtils.joiningUrlPath(pluginRestApiPrefix, "/**"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.includePatterns.isEmpty() && this.excludePatterns.isEmpty()) {
|
||||||
|
return this.interceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] include = this.includePatterns.toArray(new String[]{});
|
||||||
|
String[] exclude = this.excludePatterns.toArray(new String[]{});
|
||||||
|
MappedInterceptor mappedInterceptor = new MappedInterceptor(include, exclude, this.interceptor);
|
||||||
|
if (this.pathMatcher != null) {
|
||||||
|
mappedInterceptor.setPathMatcher(this.pathMatcher);
|
||||||
|
}
|
||||||
|
return mappedInterceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.interceptor;
|
||||||
|
|
||||||
|
import org.springframework.core.OrderComparator;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.web.context.request.WebRequestInterceptor;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
|
||||||
|
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件拦截器添加者
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class PluginInterceptorRegistry {
|
||||||
|
|
||||||
|
|
||||||
|
private final List<PluginInterceptorRegistration> registrations = new ArrayList<>();
|
||||||
|
private final String pluginRestApiPrefix;
|
||||||
|
|
||||||
|
public PluginInterceptorRegistry(String pluginRestApiPrefix) {
|
||||||
|
this.pluginRestApiPrefix = pluginRestApiPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the provided {@link HandlerInterceptor}.
|
||||||
|
* @param interceptor the interceptor to add
|
||||||
|
* @param type type {@link Type}
|
||||||
|
* @return An {@link InterceptorRegistration} that allows you optionally configure the
|
||||||
|
* registered interceptor further for example adding URL patterns it should apply to.
|
||||||
|
*/
|
||||||
|
public PluginInterceptorRegistration addInterceptor(HandlerInterceptor interceptor, Type type) {
|
||||||
|
PluginInterceptorRegistration registration = new PluginInterceptorRegistration(interceptor,
|
||||||
|
type, pluginRestApiPrefix);
|
||||||
|
this.registrations.add(registration);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the provided {@link WebRequestInterceptor}.
|
||||||
|
* @param interceptor the interceptor to add
|
||||||
|
* @param type type {@link Type}
|
||||||
|
*
|
||||||
|
* @return An {@link InterceptorRegistration} that allows you optionally configure the
|
||||||
|
* registered interceptor further for example adding URL patterns it should apply to.
|
||||||
|
*/
|
||||||
|
public PluginInterceptorRegistration addWebRequestInterceptor(WebRequestInterceptor interceptor, Type type) {
|
||||||
|
WebRequestHandlerInterceptorAdapter adapted = new WebRequestHandlerInterceptorAdapter(interceptor);
|
||||||
|
PluginInterceptorRegistration registration = new PluginInterceptorRegistration(adapted, type,
|
||||||
|
pluginRestApiPrefix);
|
||||||
|
this.registrations.add(registration);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all registered interceptors.
|
||||||
|
* @return interceptors
|
||||||
|
*/
|
||||||
|
public List<Object> getInterceptors() {
|
||||||
|
return this.registrations.stream()
|
||||||
|
.sorted(INTERCEPTOR_ORDER_COMPARATOR)
|
||||||
|
.map(PluginInterceptorRegistration::getInterceptor)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Comparator<Object> INTERCEPTOR_ORDER_COMPARATOR =
|
||||||
|
OrderComparator.INSTANCE.withSourceProvider(object -> {
|
||||||
|
if (object instanceof PluginInterceptorRegistration) {
|
||||||
|
return (Ordered) ((PluginInterceptorRegistration) object)::getOrder;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public enum Type{
|
||||||
|
/**
|
||||||
|
* 全局拦截器
|
||||||
|
*/
|
||||||
|
GLOBAL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件局部拦截器, 必须设置 pluginRestPathPrefix 的值才生效
|
||||||
|
*/
|
||||||
|
PLUGIN
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.invoke;
|
||||||
|
|
||||||
|
import com.gitee.starblues.annotation.Caller;
|
||||||
|
import com.gitee.starblues.spring.invoke.InvokeSupperCache;
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反射调用其他插件定义的接口bean工厂
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class InvokeBeanFactory<T> implements FactoryBean<T> {
|
||||||
|
|
||||||
|
private Class<T> callerInterface;
|
||||||
|
private Caller callerAnnotation;
|
||||||
|
private InvokeSupperCache invokeSupperCache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T getObject() throws Exception {
|
||||||
|
ClassLoader classLoader = callerInterface.getClassLoader();
|
||||||
|
Class<?>[] interfaces = new Class[]{callerInterface};
|
||||||
|
InvokeProxyHandler proxy = new InvokeProxyHandler(callerAnnotation, invokeSupperCache);
|
||||||
|
return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getObjectType() {
|
||||||
|
return callerInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSingleton() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallerInterface(Class<T> callerInterface) {
|
||||||
|
this.callerInterface = callerInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallerAnnotation(Caller callerAnnotation) {
|
||||||
|
this.callerAnnotation = callerAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInvokeSupperCache(InvokeSupperCache invokeSupperCache) {
|
||||||
|
this.invokeSupperCache = invokeSupperCache;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,212 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.invoke;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.gitee.starblues.annotation.Caller;
|
||||||
|
import com.gitee.starblues.annotation.Supplier;
|
||||||
|
import com.gitee.starblues.spring.invoke.InvokeSupperCache;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import com.gitee.starblues.utils.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反射调用处理模块
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class InvokeProxyHandler implements InvocationHandler {
|
||||||
|
|
||||||
|
private final Caller callerAnnotation;
|
||||||
|
|
||||||
|
private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
|
private final InvokeSupperCache invokeSupperCache;
|
||||||
|
|
||||||
|
public InvokeProxyHandler(Caller callerAnnotation, InvokeSupperCache invokeSupperCache) {
|
||||||
|
this.callerAnnotation = callerAnnotation;
|
||||||
|
this.invokeSupperCache = invokeSupperCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] callerArgs) throws Throwable {
|
||||||
|
String pluginId = callerAnnotation.pluginId();
|
||||||
|
Object supplierObject = invokeSupperCache.getSupperBean(pluginId, callerAnnotation.value());
|
||||||
|
if (supplierObject == null) {
|
||||||
|
if (ObjectUtils.isEmpty(pluginId)) {
|
||||||
|
throw new Exception("Not found '" + callerAnnotation.value() + "' supplier object");
|
||||||
|
} else {
|
||||||
|
throw new Exception("Not found '" + callerAnnotation.value() + "' supplier object in plugin '" +
|
||||||
|
pluginId + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Caller.Method callerMethod = method.getAnnotation(Caller.Method.class);
|
||||||
|
if (callerArgs == null) {
|
||||||
|
callerArgs = new Object[]{};
|
||||||
|
}
|
||||||
|
if (callerMethod == null) {
|
||||||
|
return notAnnotationInvoke(method, supplierObject, callerArgs);
|
||||||
|
} else {
|
||||||
|
return annotationInvoke(method, callerMethod, supplierObject, callerArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 有注解的调用
|
||||||
|
* @param method 调用接口的方法
|
||||||
|
* @param callerMethod 调用者方法注解
|
||||||
|
* @param supplierObject 调用者对象
|
||||||
|
* @param callerArgs 调用者参数
|
||||||
|
* @return 返回值
|
||||||
|
* @throws Throwable 异常
|
||||||
|
*/
|
||||||
|
private Object annotationInvoke(Method method, Caller.Method callerMethod,
|
||||||
|
Object supplierObject, Object[] callerArgs) throws Throwable{
|
||||||
|
|
||||||
|
String callerMethodName = callerMethod.value();
|
||||||
|
Class<?> supplierClass = supplierObject.getClass();
|
||||||
|
Method[] methods = supplierClass.getMethods();
|
||||||
|
Method supplierMethod = null;
|
||||||
|
for (Method m : methods) {
|
||||||
|
Supplier.Method supplierMethodAnnotation = m.getAnnotation(Supplier.Method.class);
|
||||||
|
if(supplierMethodAnnotation == null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(Objects.equals(supplierMethodAnnotation.value(), callerMethodName)){
|
||||||
|
supplierMethod = m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(supplierMethod == null){
|
||||||
|
// 如果为空, 说明没有找到被调用者的注解, 则走没有注解的代理调用。
|
||||||
|
return notAnnotationInvoke(method, supplierObject, callerArgs);
|
||||||
|
}
|
||||||
|
Class<?>[] parameterTypes = supplierMethod.getParameterTypes();
|
||||||
|
if(parameterTypes.length != callerArgs.length){
|
||||||
|
// 参数不匹配
|
||||||
|
return notAnnotationInvoke(method, supplierObject, callerArgs);
|
||||||
|
}
|
||||||
|
Object[] supplierArgs = getSupplierArgs(callerArgs, supplierMethod);
|
||||||
|
Object invokeReturn = supplierMethod.invoke(supplierObject, supplierArgs);
|
||||||
|
return getReturnObject(invokeReturn, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 没有注解调用
|
||||||
|
* @param method 调用接口的方法
|
||||||
|
* @param supplierObject 提供者对象
|
||||||
|
* @param callerArgs 调用者参数
|
||||||
|
* @return 返回值
|
||||||
|
* @throws Throwable 异常
|
||||||
|
*/
|
||||||
|
private Object notAnnotationInvoke(Method method, Object supplierObject, Object[] callerArgs) throws Throwable{
|
||||||
|
String name = method.getName();
|
||||||
|
Class<?>[] supplierArgClasses = new Class[callerArgs.length];
|
||||||
|
ClassLoader classLoader = supplierObject.getClass().getClassLoader();
|
||||||
|
for (int i = 0; i < callerArgs.length; i++) {
|
||||||
|
Object callerArg = callerArgs[i];
|
||||||
|
try {
|
||||||
|
supplierArgClasses[i] = classLoader.loadClass(callerArg.getClass().getName());
|
||||||
|
} catch (Exception e){
|
||||||
|
supplierArgClasses[i] = callerArg.getClass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Class<?> supplierClass = supplierObject.getClass();
|
||||||
|
Method supplierMethod = null;
|
||||||
|
try {
|
||||||
|
supplierMethod = supplierClass.getMethod(name, supplierArgClasses);
|
||||||
|
} catch (Exception e){
|
||||||
|
supplierMethod = findSupplierMethod(supplierClass, name, supplierArgClasses);
|
||||||
|
}
|
||||||
|
if(supplierMethod == null){
|
||||||
|
throw ReflectionUtils.getNoSuchMethodException(supplierClass, name, supplierArgClasses);
|
||||||
|
}
|
||||||
|
Object[] supplierArgs = getSupplierArgs(callerArgs, supplierMethod);
|
||||||
|
Object invokeReturn = supplierMethod.invoke(supplierObject, supplierArgs);
|
||||||
|
return getReturnObject(invokeReturn, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object[] getSupplierArgs(Object[] callerArgs, Method supplierMethod) throws Exception{
|
||||||
|
if(callerArgs == null || callerArgs.length == 0){
|
||||||
|
return new Class<?>[]{};
|
||||||
|
}
|
||||||
|
Class<?>[] supplierParameterTypes = supplierMethod.getParameterTypes();
|
||||||
|
Object[] supplierArgs = new Object[callerArgs.length];
|
||||||
|
for (int i = 0; i < supplierParameterTypes.length; i++) {
|
||||||
|
Class<?> supplierParameterType = supplierParameterTypes[i];
|
||||||
|
Object arg = callerArgs[i];
|
||||||
|
if(supplierParameterType.isAssignableFrom(arg.getClass())){
|
||||||
|
// 类型相同
|
||||||
|
supplierArgs[i] = arg;
|
||||||
|
} else {
|
||||||
|
// 类型不匹配, 尝试使用json序列化. 当前序列化针对大数据量下性能比较低, 建议将大数据量传输的参数定义到主程序中
|
||||||
|
String json = OBJECT_MAPPER.writeValueAsString(arg);
|
||||||
|
Object serializeObject = OBJECT_MAPPER.readValue(json, supplierParameterType);
|
||||||
|
supplierArgs[i] = serializeObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return supplierArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到返回值对象
|
||||||
|
* @param invokeReturn 反射调用后返回的对象
|
||||||
|
* @param method 调用接口的方法
|
||||||
|
* @return 返回值对象
|
||||||
|
* @throws Throwable Throwable
|
||||||
|
*/
|
||||||
|
private Object getReturnObject(Object invokeReturn, Method method) throws Throwable{
|
||||||
|
if(invokeReturn == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Class<?> returnType = method.getReturnType();
|
||||||
|
if(invokeReturn.getClass().isAssignableFrom(returnType)){
|
||||||
|
return invokeReturn;
|
||||||
|
} else {
|
||||||
|
String json = OBJECT_MAPPER.writeValueAsString(invokeReturn);
|
||||||
|
return OBJECT_MAPPER.readValue(json, OBJECT_MAPPER.getTypeFactory().constructType(method.getGenericReturnType()) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Method findSupplierMethod(Class<?> supplierClass, String methodName, Class<?>[] supplierArgClasses){
|
||||||
|
while (supplierClass != null){
|
||||||
|
Method[] methods = supplierClass.getMethods();
|
||||||
|
for (Method method : methods) {
|
||||||
|
String name = method.getName();
|
||||||
|
if(!Objects.equals(name, methodName)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(method.getParameterTypes().length == supplierArgClasses.length){
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
supplierClass = supplierClass.getSuperclass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.oneself;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.OneselfConfig;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.AnnotationUtils;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import com.gitee.starblues.utils.ResourceUtils;
|
||||||
|
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
||||||
|
import org.springframework.boot.env.PropertySourceLoader;
|
||||||
|
import org.springframework.boot.env.YamlPropertySourceLoader;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
import org.springframework.core.io.FileSystemResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件环境配置
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @version 3.0.0
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
public class ConfigureMainPluginEnvironment {
|
||||||
|
|
||||||
|
private final ProcessorContext processorContext;
|
||||||
|
private final List<PropertySourceLoader> propertySourceLoaders;
|
||||||
|
|
||||||
|
public ConfigureMainPluginEnvironment(ProcessorContext processorContext) {
|
||||||
|
this.processorContext = processorContext;
|
||||||
|
|
||||||
|
this.propertySourceLoaders = new ArrayList<>(2);
|
||||||
|
this.propertySourceLoaders.add(new YamlPropertySourceLoader());
|
||||||
|
this.propertySourceLoaders.add(new PropertiesPropertySourceLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
|
||||||
|
SpringPluginBootstrap springPluginBootstrap = processorContext.getSpringPluginBootstrap();
|
||||||
|
OneselfConfig oneselfConfig = AnnotationUtils.findAnnotation(springPluginBootstrap.getClass(),
|
||||||
|
OneselfConfig.class);
|
||||||
|
if(oneselfConfig == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String[] mainConfigFileName = oneselfConfig.mainConfigFileName();
|
||||||
|
if(mainConfigFileName.length == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String fileName : mainConfigFileName) {
|
||||||
|
load(environment, fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void load(ConfigurableEnvironment environment, String fileName){
|
||||||
|
String fileSuffix = ResourceUtils.getFileSuffix(fileName);
|
||||||
|
if(ObjectUtils.isEmpty(fileSuffix)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PropertySourceLoader sourceLoader = null;
|
||||||
|
for (PropertySourceLoader propertySourceLoader : propertySourceLoaders) {
|
||||||
|
String[] fileExtensions = propertySourceLoader.getFileExtensions();
|
||||||
|
for (String fileExtension : fileExtensions) {
|
||||||
|
if(fileSuffix.equalsIgnoreCase(fileExtension)){
|
||||||
|
sourceLoader = propertySourceLoader;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(sourceLoader == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
URL url = Objects.requireNonNull(ClassUtils.getDefaultClassLoader()).getResource(fileName);
|
||||||
|
if(url == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Path path = Paths.get(url.toURI());
|
||||||
|
Resource resource = new FileSystemResource(path);
|
||||||
|
List<PropertySource<?>> propertySources = sourceLoader.load(fileName, resource);
|
||||||
|
for (PropertySource<?> propertySource : propertySources) {
|
||||||
|
environment.getPropertySources().addFirst(propertySource);
|
||||||
|
}
|
||||||
|
} catch (Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.oneself;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorException;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.integration.operator.EmptyPluginOperator;
|
||||||
|
import com.gitee.starblues.integration.user.DefaultPluginUser;
|
||||||
|
import com.gitee.starblues.spring.extract.DefaultOpExtractFactory;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子启动处理器
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @version 3.1.0
|
||||||
|
* @since 3.0.4
|
||||||
|
*/
|
||||||
|
public class OneselfProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ProcessorContext context) throws ProcessorException {
|
||||||
|
registerMainBean(context.getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.ONESELF;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerMainBean(GenericApplicationContext applicationContext){
|
||||||
|
DefaultListableBeanFactory beanFactory = applicationContext.getDefaultListableBeanFactory();
|
||||||
|
beanFactory.registerSingleton("extractFactory", new DefaultOpExtractFactory());
|
||||||
|
beanFactory.registerSingleton("pluginUser", new DefaultPluginUser(applicationContext));
|
||||||
|
beanFactory.registerSingleton("pluginOperator", new EmptyPluginOperator());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.scanner;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件自定义 classpath bean 扫描
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class PluginClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
|
||||||
|
|
||||||
|
public PluginClassPathBeanDefinitionScanner(ProcessorContext processorContext) {
|
||||||
|
this(processorContext, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginClassPathBeanDefinitionScanner(ProcessorContext processorContext, boolean useDefaultFilters) {
|
||||||
|
super(processorContext.getApplicationContext(), useDefaultFilters,
|
||||||
|
processorContext.getApplicationContext().getEnvironment(),
|
||||||
|
processorContext.getResourceLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,266 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.web;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorException;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.AnnotationUtils;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.DestroyUtils;
|
||||||
|
import com.gitee.starblues.integration.IntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.spring.SpringBeanFactory;
|
||||||
|
import com.gitee.starblues.utils.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.servlet.mvc.condition.RequestCondition;
|
||||||
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
|
||||||
|
import java.lang.reflect.AnnotatedElement;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件Controller处理者
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.1
|
||||||
|
*/
|
||||||
|
public class PluginControllerProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(PluginControllerProcessor.class);
|
||||||
|
|
||||||
|
static final String PROCESS_CONTROLLERS = "PROCESS_SUCCESS";
|
||||||
|
|
||||||
|
|
||||||
|
private RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||||
|
private RequestMappingHandlerAdapter handlerAdapter;
|
||||||
|
|
||||||
|
private final AtomicBoolean canRegistered = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ProcessorContext processorContext) throws ProcessorException {
|
||||||
|
MainApplicationContext mainApplicationContext = processorContext.getMainApplicationContext();
|
||||||
|
this.requestMappingHandlerMapping = mainApplicationContext.getRequestMappingHandlerMapping();
|
||||||
|
this.handlerAdapter = mainApplicationContext.getRequestMappingHandlerAdapter();
|
||||||
|
canRegistered.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshBefore(ProcessorContext processorContext) throws ProcessorException {
|
||||||
|
if(!canRegistered.get()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GenericApplicationContext applicationContext = processorContext.getApplicationContext();
|
||||||
|
applicationContext.getDefaultListableBeanFactory()
|
||||||
|
.addBeanPostProcessor(new ControllerPostProcessor(processorContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshAfter(ProcessorContext processorContext) throws ProcessorException {
|
||||||
|
if(!canRegistered.get()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String pluginId = processorContext.getPluginDescriptor().getPluginId();
|
||||||
|
List<ControllerWrapper> controllerWrappers = processorContext.getRegistryInfo(PROCESS_CONTROLLERS);
|
||||||
|
if(ObjectUtils.isEmpty(controllerWrappers)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GenericApplicationContext applicationContext = processorContext.getApplicationContext();
|
||||||
|
|
||||||
|
Iterator<ControllerWrapper> iterator = controllerWrappers.iterator();
|
||||||
|
String pathPrefix = PluginConfigUtils.getPluginRestPrefix(processorContext.getConfiguration(), pluginId);
|
||||||
|
PluginRequestMappingHandlerMapping pluginHandlerMapping = new PluginRequestMappingHandlerMapping(pathPrefix);
|
||||||
|
|
||||||
|
while (iterator.hasNext()){
|
||||||
|
ControllerWrapper controllerWrapper = iterator.next();
|
||||||
|
if(!applicationContext.containsBean(controllerWrapper.getBeanName())){
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
Object controllerBean = applicationContext.getBean(controllerWrapper.getBeanName());
|
||||||
|
pluginHandlerMapping.registerHandler(controllerBean);
|
||||||
|
List<RegisterMappingInfo> registerMappingInfo = pluginHandlerMapping.getAndClear();
|
||||||
|
|
||||||
|
Set<RequestMappingInfo> requestMappingInfoSet = new HashSet<>(registerMappingInfo.size());
|
||||||
|
for (RegisterMappingInfo mappingInfo : registerMappingInfo) {
|
||||||
|
RequestMappingInfo requestMappingInfo = mappingInfo.getRequestMappingInfo();
|
||||||
|
requestMappingHandlerMapping.registerMapping(
|
||||||
|
requestMappingInfo,
|
||||||
|
mappingInfo.getHandler(),
|
||||||
|
mappingInfo.getMethod()
|
||||||
|
);
|
||||||
|
LOG.info("插件[{}]注册接口: {}", pluginId, requestMappingInfo);
|
||||||
|
requestMappingInfoSet.add(requestMappingInfo);
|
||||||
|
}
|
||||||
|
controllerWrapper.setRequestMappingInfo(requestMappingInfoSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(ProcessorContext context) throws ProcessorException {
|
||||||
|
List<ControllerWrapper> controllerWrappers = context.getRegistryInfo(PROCESS_CONTROLLERS);
|
||||||
|
if(ObjectUtils.isEmpty(controllerWrappers)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (ControllerWrapper controllerWrapper : controllerWrappers) {
|
||||||
|
unregister(controllerWrapper);
|
||||||
|
}
|
||||||
|
controllerWrappers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.PLUGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 卸载具体的Controller操作
|
||||||
|
* @param controllerBeanWrapper controllerBean包装
|
||||||
|
*/
|
||||||
|
private void unregister(ControllerWrapper controllerBeanWrapper) {
|
||||||
|
Set<RequestMappingInfo> requestMappingInfoSet = controllerBeanWrapper.getRequestMappingInfo();
|
||||||
|
if(requestMappingInfoSet != null && !requestMappingInfoSet.isEmpty()){
|
||||||
|
for (RequestMappingInfo requestMappingInfo : requestMappingInfoSet) {
|
||||||
|
requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(handlerAdapter != null){
|
||||||
|
Class<?> beanClass = controllerBeanWrapper.getBeanClass();
|
||||||
|
DestroyUtils.destroyValue(handlerAdapter, "sessionAttributesHandlerCache", beanClass);
|
||||||
|
DestroyUtils.destroyValue(handlerAdapter, "initBinderCache", beanClass);
|
||||||
|
DestroyUtils.destroyValue(handlerAdapter, "modelAttributeCache", beanClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ControllerPostProcessor implements BeanPostProcessor {
|
||||||
|
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(ControllerPostProcessor.class);
|
||||||
|
|
||||||
|
private final ProcessorContext processorContext;
|
||||||
|
|
||||||
|
private ControllerPostProcessor(ProcessorContext processorContext) {
|
||||||
|
this.processorContext = processorContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
Class<?> aClass = bean.getClass();
|
||||||
|
RequestMapping requestMapping = AnnotationUtils.findAnnotation(aClass, RequestMapping.class);
|
||||||
|
boolean isController = AnnotationUtils.existOr(aClass, new Class[]{
|
||||||
|
Controller.class, RestController.class
|
||||||
|
});
|
||||||
|
if(requestMapping != null && isController){
|
||||||
|
addControllerWrapper(beanName, aClass);
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addControllerWrapper(String beanName, Class<?> aClass){
|
||||||
|
List<ControllerWrapper> controllerWrappers = processorContext.getRegistryInfo(PROCESS_CONTROLLERS);
|
||||||
|
if(controllerWrappers == null){
|
||||||
|
controllerWrappers = new ArrayList<>();
|
||||||
|
processorContext.addRegistryInfo(PROCESS_CONTROLLERS, controllerWrappers);
|
||||||
|
}
|
||||||
|
ControllerWrapper controllerWrapper = new ControllerWrapper();
|
||||||
|
controllerWrapper.setBeanName(beanName);
|
||||||
|
controllerWrapper.setBeanClass(aClass);
|
||||||
|
controllerWrappers.add(controllerWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class ControllerWrapper{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* controller bean 名称
|
||||||
|
*/
|
||||||
|
private String beanName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* controller bean 类型
|
||||||
|
*/
|
||||||
|
private Class<?> beanClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* controller 的 RequestMappingInfo 集合
|
||||||
|
*/
|
||||||
|
private Set<RequestMappingInfo> requestMappingInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class PluginRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
|
||||||
|
|
||||||
|
private final List<RegisterMappingInfo> registerMappingInfo = new ArrayList<>();
|
||||||
|
|
||||||
|
public PluginRequestMappingHandlerMapping(){
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginRequestMappingHandlerMapping(String pathPrefix){
|
||||||
|
if(!ObjectUtils.isEmpty(pathPrefix)){
|
||||||
|
Map<String, Predicate<Class<?>>> prefixes = new HashMap<>();
|
||||||
|
prefixes.put(pathPrefix, c->true);
|
||||||
|
setPathPrefixes(prefixes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerHandler(Object handler){
|
||||||
|
detectHandlerMethods(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
|
||||||
|
super.registerHandlerMethod(handler, method, mapping);
|
||||||
|
registerMappingInfo.add(new RegisterMappingInfo(handler, method, mapping));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RegisterMappingInfo> getAndClear(){
|
||||||
|
List<RegisterMappingInfo> registerMappingInfo = new ArrayList<>(this.registerMappingInfo);
|
||||||
|
this.registerMappingInfo.clear();
|
||||||
|
return registerMappingInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
private static class RegisterMappingInfo{
|
||||||
|
private final Object handler;
|
||||||
|
private final Method method;
|
||||||
|
private final RequestMappingInfo requestMappingInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.web;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorException;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.interceptor.PluginInterceptorRegister;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.interceptor.PluginInterceptorRegistry;
|
||||||
|
import com.gitee.starblues.bootstrap.utils.SpringBeanUtils;
|
||||||
|
import com.gitee.starblues.integration.IntegrationConfiguration;
|
||||||
|
import com.gitee.starblues.spring.MainApplicationContext;
|
||||||
|
import com.gitee.starblues.utils.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
|
import org.springframework.web.context.request.WebRequestInterceptor;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.web.servlet.HandlerMapping;
|
||||||
|
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
|
||||||
|
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件拦截器处理者
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class PluginInterceptorsProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
private final static String INTERCEPTORS = "pluginHandlerInterceptors";
|
||||||
|
|
||||||
|
private List<AbstractHandlerMapping> handlerMappings;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ProcessorContext context) throws ProcessorException {
|
||||||
|
MainApplicationContext applicationContext = context.getMainApplicationContext();
|
||||||
|
handlerMappings = SpringBeanCustomUtils.getBeans(applicationContext,
|
||||||
|
AbstractHandlerMapping.class);
|
||||||
|
if(handlerMappings.isEmpty()){
|
||||||
|
logger.warn("Not found AbstractHandlerMapping, Plugin interceptor can't use");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshAfter(ProcessorContext context) throws ProcessorException {
|
||||||
|
if(handlerMappings.isEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<PluginInterceptorRegister> interceptorRegisters = SpringBeanUtils.getBeans(
|
||||||
|
context.getApplicationContext(),
|
||||||
|
PluginInterceptorRegister.class);
|
||||||
|
|
||||||
|
Map<AbstractHandlerMapping, List<HandlerInterceptor>> handlerInterceptorMap = new HashMap<>();
|
||||||
|
for (AbstractHandlerMapping handlerMapping : handlerMappings) {
|
||||||
|
List<HandlerInterceptor> adaptedInterceptors = getAdaptedInterceptors(handlerMapping);
|
||||||
|
if(!ObjectUtils.isEmpty(adaptedInterceptors)){
|
||||||
|
handlerInterceptorMap.put(handlerMapping, adaptedInterceptors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(handlerInterceptorMap.isEmpty()){
|
||||||
|
logger.debug("handlerInterceptorMap is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IntegrationConfiguration configuration = context.getConfiguration();
|
||||||
|
String pluginId = context.getPluginDescriptor().getPluginId();
|
||||||
|
String pluginRestPrefix = PluginConfigUtils.getPluginRestPrefix(configuration, pluginId);
|
||||||
|
|
||||||
|
|
||||||
|
List<HandlerInterceptor> storeInterceptors = new ArrayList<>();
|
||||||
|
for (PluginInterceptorRegister interceptorRegister : interceptorRegisters) {
|
||||||
|
PluginInterceptorRegistry interceptorRegistry = new PluginInterceptorRegistry(pluginRestPrefix);
|
||||||
|
interceptorRegister.registry(interceptorRegistry);
|
||||||
|
List<Object> registryInterceptors = interceptorRegistry.getInterceptors();
|
||||||
|
if(registryInterceptors == null || registryInterceptors.isEmpty()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (Object interceptor : registryInterceptors) {
|
||||||
|
HandlerInterceptor handlerInterceptor = adaptInterceptor(interceptor);
|
||||||
|
for (List<HandlerInterceptor> value : handlerInterceptorMap.values()) {
|
||||||
|
value.add(handlerInterceptor);
|
||||||
|
}
|
||||||
|
storeInterceptors.add(handlerInterceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.addRegistryInfo(INTERCEPTORS, storeInterceptors);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(ProcessorContext context) throws ProcessorException {
|
||||||
|
if(handlerMappings.isEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<HandlerInterceptor> storeInterceptors = context.getRegistryInfo(INTERCEPTORS);
|
||||||
|
if(ObjectUtils.isEmpty(storeInterceptors)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (HandlerInterceptor storeInterceptor : storeInterceptors) {
|
||||||
|
for (AbstractHandlerMapping handlerMapping : handlerMappings) {
|
||||||
|
List<HandlerInterceptor> adaptedInterceptors = getAdaptedInterceptors(handlerMapping);
|
||||||
|
if(!ObjectUtils.isEmpty(adaptedInterceptors)){
|
||||||
|
adaptedInterceptors.remove(storeInterceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.PLUGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到拦截器存储者
|
||||||
|
* @param handlerMapping AbstractHandlerMapping
|
||||||
|
* @return List<HandlerInterceptor>
|
||||||
|
*/
|
||||||
|
private List<HandlerInterceptor> getAdaptedInterceptors(AbstractHandlerMapping handlerMapping){
|
||||||
|
try {
|
||||||
|
return ClassUtils.getReflectionField(handlerMapping, "adaptedInterceptors", List.class);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
logger.error("Can't get 'adaptedInterceptors' from AbstractHandlerMapping, so " +
|
||||||
|
"You can't use HandlerInterceptor. {} ", e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换拦截器
|
||||||
|
* @param interceptor interceptor
|
||||||
|
* @return HandlerInterceptor
|
||||||
|
*/
|
||||||
|
private HandlerInterceptor adaptInterceptor(Object interceptor) {
|
||||||
|
if (interceptor instanceof HandlerInterceptor) {
|
||||||
|
return (HandlerInterceptor) interceptor;
|
||||||
|
} else if (interceptor instanceof WebRequestInterceptor) {
|
||||||
|
return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.processor.web;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorContext;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.ProcessorException;
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
import com.gitee.starblues.utils.ObjectUtils;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件web资源处理器. 获取资源配置
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class PluginStaticResourceProcessor implements SpringPluginProcessor {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 静态文件配置前缀
|
||||||
|
* 静态文件路径
|
||||||
|
* classpath: static/
|
||||||
|
* file: D://path/test
|
||||||
|
*/
|
||||||
|
private final static String STATIC_LOCATIONS = "spring.resources.static-locations";
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshBefore(ProcessorContext context) throws ProcessorException {
|
||||||
|
GenericApplicationContext applicationContext = context.getApplicationContext();
|
||||||
|
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
||||||
|
String property = environment.getProperty(STATIC_LOCATIONS);
|
||||||
|
if(ObjectUtils.isEmpty(property)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String[] staticLocations = property.split(",");
|
||||||
|
if (ObjectUtils.isEmpty(staticLocations)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<String> staticLocationsSet = new HashSet<>(staticLocations.length);
|
||||||
|
for (String staticLocation : staticLocations) {
|
||||||
|
if(ObjectUtils.isEmpty(staticLocation)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
staticLocationsSet.add(staticLocation);
|
||||||
|
}
|
||||||
|
context.getWebConfig().setResourceLocations(staticLocationsSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorContext.RunMode runMode() {
|
||||||
|
return ProcessorContext.RunMode.PLUGIN;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.realize;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.AutowiredTypeDefinerConfig;
|
||||||
|
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
|
||||||
|
import com.gitee.starblues.utils.UrlUtils;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* autowiredType 批量定义接口
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.3
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public interface AutowiredTypeDefiner {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义 ClassDefiner
|
||||||
|
* @param config 往config中进行配置 ClassDefiner
|
||||||
|
*/
|
||||||
|
void config(AutowiredTypeDefinerConfig config);
|
||||||
|
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@EqualsAndHashCode
|
||||||
|
class ClassDefiner{
|
||||||
|
/**
|
||||||
|
* 注入类型
|
||||||
|
*/
|
||||||
|
private final AutowiredType.Type autowiredType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类名称匹配
|
||||||
|
*/
|
||||||
|
private final Set<String> classNamePatterns;
|
||||||
|
|
||||||
|
private ClassDefiner(AutowiredType.Type autowiredType, Set<String> classNamePatterns){
|
||||||
|
this.autowiredType = autowiredType;
|
||||||
|
this.classNamePatterns = classNamePatterns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassDefiner config(AutowiredType.Type autowiredType, Class<?>... classes){
|
||||||
|
if(autowiredType == null){
|
||||||
|
throw new IllegalArgumentException("autowiredType 参数不能为空");
|
||||||
|
}
|
||||||
|
int length = classes.length;
|
||||||
|
if(length == 0){
|
||||||
|
throw new IllegalArgumentException("classes 参数不能为空");
|
||||||
|
}
|
||||||
|
Set<String> classNamePatterns = new HashSet<>(length);
|
||||||
|
for (Class<?> aClass : classes) {
|
||||||
|
classNamePatterns.add(UrlUtils.formatMatchUrl(aClass.getName()));
|
||||||
|
}
|
||||||
|
return new ClassDefiner(autowiredType, classNamePatterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassDefiner config(AutowiredType.Type autowiredType, String... classNamePatterns){
|
||||||
|
if(autowiredType == null){
|
||||||
|
throw new IllegalArgumentException("autowiredType 参数不能为空");
|
||||||
|
}
|
||||||
|
int length = classNamePatterns.length;
|
||||||
|
if(length == 0){
|
||||||
|
throw new IllegalArgumentException("classNamePatterns 参数不能为空");
|
||||||
|
}
|
||||||
|
Set<String> classNamePatternsSet = new HashSet<>(length);
|
||||||
|
for (String classNamePattern : classNamePatterns) {
|
||||||
|
classNamePatternsSet.add(UrlUtils.formatMatchUrl(classNamePattern));
|
||||||
|
}
|
||||||
|
return new ClassDefiner(autowiredType, classNamePatternsSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.realize;
|
||||||
|
|
||||||
|
import com.gitee.starblues.core.PluginCloseType;
|
||||||
|
import com.gitee.starblues.core.PluginInfo;
|
||||||
|
import com.gitee.starblues.core.descriptor.PluginDescriptor;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件被停止监听者。用于自定义关闭资源
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.1.0
|
||||||
|
*/
|
||||||
|
public interface PluginCloseListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭时调用
|
||||||
|
* @param descriptor 当前插件描述者
|
||||||
|
* @deprecated 在 3.1.1 版本会被删除
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
default void close(PluginDescriptor descriptor){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭时调用
|
||||||
|
* @param applicationContext 当前插件的ApplicationContext
|
||||||
|
* @param pluginInfo 当前插件信息
|
||||||
|
* @param closeType 停止类型
|
||||||
|
* @since 3.1.0
|
||||||
|
*/
|
||||||
|
default void close(GenericApplicationContext applicationContext,
|
||||||
|
PluginInfo pluginInfo, PluginCloseType closeType){
|
||||||
|
close(pluginInfo != null ? pluginInfo.getPluginDescriptor() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.realize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件停止校验器. 自主实现判断是否可卸载
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.3
|
||||||
|
*/
|
||||||
|
public interface StopValidator {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验是否可停止/卸载。如果校验器抛出异常. 默认插件不可停止/卸载
|
||||||
|
* @return 校验结果
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
|
Result verify();
|
||||||
|
|
||||||
|
|
||||||
|
class Result{
|
||||||
|
/**
|
||||||
|
* 是否可卸载
|
||||||
|
*/
|
||||||
|
private final boolean verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不可卸载时的提示内容
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
|
||||||
|
public Result(boolean verify) {
|
||||||
|
this.verify = verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result(boolean verify, String message) {
|
||||||
|
this.verify = verify;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可卸载
|
||||||
|
* @return Result
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public static Result ok(){
|
||||||
|
return new Result(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁止停止
|
||||||
|
* @return Result
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public static Result forbid(){
|
||||||
|
return forbid(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁止停止
|
||||||
|
* @param message 禁止停止信息
|
||||||
|
* @return Result
|
||||||
|
* @since 3.0.3
|
||||||
|
*/
|
||||||
|
public static Result forbid(String message){
|
||||||
|
return new Result(false, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVerify() {
|
||||||
|
return verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注解工具类
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class AnnotationUtils {
|
||||||
|
|
||||||
|
|
||||||
|
private AnnotationUtils(){}
|
||||||
|
|
||||||
|
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
|
||||||
|
return org.springframework.core.annotation.AnnotationUtils.findAnnotation(method, annotationType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
|
||||||
|
return org.springframework.core.annotation.AnnotationUtils.findAnnotation(clazz, annotationType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <A extends Annotation> boolean existOr(Class<?> clazz, Class<A>[] annotationTypes) {
|
||||||
|
for (Class<A> annotationType : annotationTypes) {
|
||||||
|
A annotation = findAnnotation(clazz, annotationType);
|
||||||
|
if(annotation != null){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <A extends Annotation> boolean existAnd(Class<?> clazz, Class<A>[] annotationTypes) {
|
||||||
|
for (Class<A> annotationType : annotationTypes) {
|
||||||
|
A annotation = findAnnotation(clazz, annotationType);
|
||||||
|
if(annotation == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.utils;
|
||||||
|
|
||||||
|
import com.gitee.starblues.utils.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁工具类
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class DestroyUtils {
|
||||||
|
|
||||||
|
private DestroyUtils(){}
|
||||||
|
|
||||||
|
public static void destroyAll(Object object, String fieldName, Class<?> fieldType){
|
||||||
|
destroyAll(object, object.getClass(), fieldName, fieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destroyAll(Object object, Class<?> objectClass, String fieldName, Class<?> fieldType){
|
||||||
|
try {
|
||||||
|
Object fieldObject = ReflectionUtils.getField(object, objectClass, fieldName, fieldType);
|
||||||
|
if(fieldObject == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
destroyAll(fieldObject);
|
||||||
|
} catch (Exception e){
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destroyValue(Object object, String fieldName, Object value){
|
||||||
|
destroyValue(object, object.getClass(), fieldName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destroyValue(Object object, Class<?> objectClass, String fieldName, Object value){
|
||||||
|
destroyValue(object, objectClass, fieldName, null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void destroyValue(Object object, Class<?> objectClass, String fieldName, Class<?> fieldType, Object value){
|
||||||
|
try {
|
||||||
|
Object fieldObject = ReflectionUtils.getField(object, objectClass, fieldName, fieldType);
|
||||||
|
if(fieldObject == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
destroyValue(fieldObject, value);
|
||||||
|
} catch (Exception e){
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static void destroyAll(Object object){
|
||||||
|
if(object == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(object instanceof Map){
|
||||||
|
((Map)object).clear();
|
||||||
|
} else if (object instanceof Collection){
|
||||||
|
((Collection)object).clear();
|
||||||
|
} else if(object.getClass().isArray()){
|
||||||
|
Object[] array = (Object[])object;
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
array[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static void destroyValue(Object object, Object value){
|
||||||
|
if(object == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(object instanceof Map){
|
||||||
|
((Map)object).remove(value);
|
||||||
|
} else if (object instanceof Collection){
|
||||||
|
((Collection) object).removeIf(next -> Objects.equals(next, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* Copyright [2019-Present] [starBlues]
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.gitee.starblues.bootstrap.utils;
|
||||||
|
|
||||||
|
import com.gitee.starblues.bootstrap.processor.SpringPluginProcessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProcessorUtils
|
||||||
|
*
|
||||||
|
* @author starBlues
|
||||||
|
* @since 3.0.0
|
||||||
|
* @version 3.0.0
|
||||||
|
*/
|
||||||
|
public class ProcessorUtils {
|
||||||
|
|
||||||
|
public static void add(List<SpringPluginProcessor> pluginProcessors, Supplier<SpringPluginProcessor> supplier){
|
||||||
|
try {
|
||||||
|
SpringPluginProcessor pluginProcessor = supplier.get();
|
||||||
|
pluginProcessors.add(pluginProcessor);
|
||||||
|
} catch (Throwable e){
|
||||||
|
// 忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue