feature #I4UPWG 模块架构调整,支持非Spring的项目使用

This commit is contained in:
bryan31
2022-02-22 14:13:26 +08:00
parent cf6a527f97
commit 714914687f
97 changed files with 1013 additions and 261 deletions

View File

@@ -0,0 +1,27 @@
package com.yomahub.liteflow.annotation;
import org.springframework.stereotype.Component;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**
* LiteFlow的组件标识注解
*
* @author Bryan.Zhang
* @since 2.6.0
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Component
public @interface LiteflowComponent {
@AliasFor(annotation = Component.class, attribute = "value")
String value() default "";
@AliasFor(annotation = Component.class, attribute = "value")
String id() default "";
String name() default "";
}

View File

@@ -0,0 +1,81 @@
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.yomahub.liteflow.spi.ContextAware;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* 基于代码形式的spring上下文工具类
* @author Bryan.Zhang
*/
public class SpringAware implements ApplicationContextAware, ContextAware {
private static ApplicationContext applicationContext = null;
public SpringAware() {
}
public void setApplicationContext(ApplicationContext ac) throws BeansException {
applicationContext = ac;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public <T> T getBean(String name) {
try{
T t = (T) applicationContext.getBean(name);
return t;
}catch (Exception e){
return null;
}
}
public <T> T getBean(Class<T> clazz) {
try{
T t = applicationContext.getBean(clazz);
return t;
}catch (Exception e){
return null;
}
}
public <T> T registerBean(String beanName, Class<T> c) {
try{
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName(c.getName());
beanFactory.registerBeanDefinition(beanName, beanDefinition);
return getBean(beanName);
}catch (Exception e){
return ReflectUtil.newInstance(c);
}
}
public <T> T registerBean(Class<T> c) {
return registerBean(c.getName(), c);
}
public <T> T registerOrGet(String beanName, Class<T> clazz) {
if (ObjectUtil.isNull(applicationContext)){
return null;
}
T t = getBean(clazz);
if (ObjectUtil.isNull(t)) {
t = registerBean(beanName, clazz);
}
return t;
}
@Override
public int priority() {
return 1;
}
}

View File

@@ -0,0 +1,32 @@
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.entity.data.Slot;
import com.yomahub.liteflow.spi.CmpAroundAspect;
import com.yomahub.liteflow.spring.ComponentScanner;
/**
* Spring环境全局组件切面实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class SpringCmpAroundAspect implements CmpAroundAspect {
@Override
public void beforeProcess(String nodeId, Slot slot) {
if (ObjectUtil.isNotNull(ComponentScanner.cmpAroundAspect)) {
ComponentScanner.cmpAroundAspect.beforeProcess(nodeId, slot);
}
}
@Override
public void afterProcess(String nodeId, Slot slot) {
if (ObjectUtil.isNotNull(ComponentScanner.cmpAroundAspect)) {
ComponentScanner.cmpAroundAspect.afterProcess(nodeId, slot);
}
}
@Override
public int priority() {
return 1;
}
}

View File

@@ -0,0 +1,29 @@
package com.yomahub.liteflow.spi.spring;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.spi.ContextCmpInit;
import com.yomahub.liteflow.spring.ComponentScanner;
import java.util.Map;
/**
* Spring环境容器上下文组件初始化实现
* @author Bryan.Zhang
* @since 2.6.11
*/
public class SpringContextCmpInit implements ContextCmpInit {
@Override
public void initCmp() {
for (Map.Entry<String, NodeComponent> componentEntry : ComponentScanner.nodeComponentMap.entrySet()) {
if (!FlowBus.containNode(componentEntry.getKey())) {
FlowBus.addSpringScanNode(componentEntry.getKey(), componentEntry.getValue());
}
}
}
@Override
public int priority() {
return 1;
}
}

View File

@@ -0,0 +1,31 @@
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.spi.LiteflowComponentSupport;
/**
* spring环境LiteflowComponent注解的处理器
* @author Bryan.Zhang
* @since 2.6.11
*/
public class SpringLiteflowComponentSupport implements LiteflowComponentSupport {
@Override
public String getCmpName(NodeComponent nodeComponent) {
//判断NodeComponent是否是标识了@LiteflowComponent的标注
//如果标注了那么要从中取到name字段
LiteflowComponent liteflowComponent = nodeComponent.getClass().getAnnotation(LiteflowComponent.class);
if (ObjectUtil.isNotNull(liteflowComponent)) {
return liteflowComponent.name();
}else{
return null;
}
}
@Override
public int priority() {
return 1;
}
}

View File

@@ -0,0 +1,74 @@
package com.yomahub.liteflow.spi.spring;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.exception.ConfigErrorException;
import com.yomahub.liteflow.spi.PathContentParser;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ResourceUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class SpringPathContentParser implements PathContentParser {
@Override
public List<String> parseContent(List<String> pathList) throws Exception {
if(CollectionUtil.isEmpty(pathList)){
throw new ConfigErrorException("rule source must not be null");
}
List<Resource> allResource = new ArrayList<>();
for (String path : pathList) {
String locationPattern;
//如果path是绝对路径且这个文件存在时我们认为这是一个本地文件路径而并非classpath路径
if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)){
locationPattern = ResourceUtils.FILE_URL_PREFIX + path;
} else {
if (!path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
locationPattern = ResourceUtils.CLASSPATH_URL_PREFIX + path;
}else{
locationPattern = path;
}
}
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources(locationPattern);
if (ArrayUtil.isEmpty(resources)) {
throw new ConfigErrorException("config error,please check rule source property");
}
allResource.addAll(ListUtil.toList(resources));
}
//如果有多个资源,检查资源都是同一个类型,如果出现不同类型的配置,则抛出错误提示
Set<String> fileTypeSet = new HashSet<>();
allResource.forEach(resource -> fileTypeSet.add(FileUtil.extName(resource.getFilename())));
if (fileTypeSet.size() != 1) {
throw new ConfigErrorException("config error,please use the same type of configuration");
}
//转换成内容List
List<String> contentList = new ArrayList<>();
for (Resource resource : allResource) {
String content = IoUtil.read(resource.getInputStream(), CharsetUtil.CHARSET_UTF_8);
if (StrUtil.isNotBlank(content)){
contentList.add(content);
}
}
return contentList;
}
@Override
public int priority() {
return 1;
}
}

View File

@@ -0,0 +1,78 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
*
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.spring;
import com.yomahub.liteflow.aop.ICmpAroundAspect;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.util.LOGOPrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.util.HashMap;
import java.util.Map;
/**
* 组件扫描类只要是NodeComponent的实现类都可以被这个扫描器扫到
* @author Bryan.Zhang
*/
public class ComponentScanner implements BeanPostProcessor {
private static final Logger LOG = LoggerFactory.getLogger(ComponentScanner.class);
public static Map<String, NodeComponent> nodeComponentMap = new HashMap<>();
private LiteflowConfig liteflowConfig;
public static ICmpAroundAspect cmpAroundAspect;
public ComponentScanner() {
LOGOPrinter.print();
}
public ComponentScanner(LiteflowConfig liteflowConfig) {
this.liteflowConfig = liteflowConfig;
if(liteflowConfig.getPrintBanner()){
// 打印liteflow的LOGO
LOGOPrinter.print();
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@SuppressWarnings("rawtypes")
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class clazz = bean.getClass();
// 组件的扫描发现扫到之后缓存到类属性map中
if (NodeComponent.class.isAssignableFrom(clazz)) {
LOG.info("component[{}] has been found", beanName);
NodeComponent nodeComponent = (NodeComponent) bean;
nodeComponentMap.put(beanName, nodeComponent);
}
// 组件Aop的实现类加载
if (ICmpAroundAspect.class.isAssignableFrom(clazz)) {
LOG.info("component aspect implement[{}] has been found", beanName);
cmpAroundAspect = (ICmpAroundAspect) bean;
}
return bean;
}
//用于清楚spring上下文扫描到的组件实体
public static void cleanCache() {
nodeComponentMap.clear();
}
}