Commit cf451604 authored by 薛涛 Toby Xue's avatar 薛涛 Toby Xue 🆒

#1971

parent f80bd7c1
Pipeline #4313 canceled with stages
package logwire.web.bo;
import logwire.core.resource.JavaBeanContainer;
import logwire.core.resource.JavaBeanContainerBuilder;
import logwire.core.resource.Util;
import logwire.web.bo.loader.BoRelationBeanDefinitionLoader;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class BoRelationBeanContainerBuilder implements JavaBeanContainerBuilder {
public static final String CONTAINER_NAME = "BO_RELATION_CONTAINER";
@Override
public JavaBeanContainer build(ApplicationContext applicationContext) {
return new JavaBeanContainer(Util.getExactBean(applicationContext, BoRelationBeanDefinitionLoader.class));
}
@Override
public String getContainerName() {
return CONTAINER_NAME;
}
}
package logwire.web.bo;
import logwire.core.exceptions.ApplicationException;
import logwire.web.bo.proxy.Proxy;
import logwire.web.service.query.QueryService;
import logwire.web.tenant.TenantProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class BoService {
@Autowired
QueryService queryService;
@Autowired
TenantProjectService tenantProjectService;
public Object createBizObject(Class clazz) {
Map<String, BoRelationDefinition> boRelationDefinitions = (Map<String, BoRelationDefinition>) tenantProjectService.getCurrentProject().getBeansByContainerName(BoRelationBeanContainerBuilder.CONTAINER_NAME);
BoRelationDefinition boRelationDefinition = boRelationDefinitions.get(clazz.getName());
if (boRelationDefinition != null) {
try {
return Proxy.createObjectOperationProvider(boRelationDefinition, boRelationDefinitions);
} catch (IllegalAccessException | InstantiationException e) {
throw ApplicationException.wrap(e);
}
}
return null;
}
}
......@@ -2,19 +2,13 @@ package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.BigIntegerField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class BigIntegerFieldParser extends FieldParser<BigIntegerField> {
@Override
protected BigIntegerField newField(Field field, Annotation[] annotations) {
return new BigIntegerField(field.getName());
}
@Override
protected void setField(BigIntegerField newField, Annotation[] annotations) {
protected BigIntegerField newField(String name, Field field) {
return new BigIntegerField(name);
}
private BigIntegerFieldParser() {
......
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.StringField;
import logwire.core.meta.model.fields.MultipleChoiceField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class BizArrayFieldParser extends FieldParser<StringField> {
public class BizArrayFieldParser extends FieldParser<MultipleChoiceField> {
@Override
protected StringField newField(Field field, Annotation[] annotations) {
return new StringField(field.getName(), 100);
protected MultipleChoiceField newField(String name, Field field) {
return new MultipleChoiceField(name, 100);
}
private BizArrayFieldParser() {
......
......@@ -2,13 +2,12 @@ package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.BooleanField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class BooleanFieldParser extends FieldParser<BooleanField> {
@Override
protected BooleanField newField(Field field, Annotation[] annotations) {
return new BooleanField(field.getName());
protected BooleanField newField(String name, Field field) {
return new BooleanField(name);
}
private BooleanFieldParser() {
......
package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.ChoiceField;
import java.lang.reflect.Field;
public class ChoiceFieldParser extends FieldParser<ChoiceField> {
@Override
protected ChoiceField newField(String name, Field field) {
return new ChoiceField(name, 50);
}
private ChoiceFieldParser() {
}
public static ChoiceFieldParser getInstance() {
return ChoiceFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static ChoiceFieldParser instance = new ChoiceFieldParser();
}
}
......@@ -2,14 +2,13 @@ package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.DateTimeField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class DateTimeFieldParser extends FieldParser<DateTimeField> {
@Override
protected DateTimeField newField(Field field, Annotation[] annotations) {
return new DateTimeField(field.getName());
protected DateTimeField newField(String name, Field field) {
return new DateTimeField(name);
}
private DateTimeFieldParser() {
......
......@@ -2,14 +2,13 @@ package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.DecimalField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class DecimalFieldParser extends FieldParser<DecimalField> {
@Override
protected DecimalField newField(Field field, Annotation[] annotations) {
return new DecimalField(field.getName(), 18, 6);
protected DecimalField newField(String name, Field field) {
return new DecimalField(name, 18, 6);
}
private DecimalFieldParser() {
......
package logwire.web.bo.field.parse;
import java.lang.annotation.Annotation;
import logwire.core.bo.annotation.Array;
import logwire.core.bo.annotation.Column;
import java.lang.reflect.Field;
public abstract class FieldParser<T extends logwire.core.meta.model.fields.Field> {
protected abstract T newField(Field field, Annotation[] annotations);
protected abstract T newField(String name, Field field);
public T parse(Field field, Annotation[] annotations) {
T newField = newField(field, annotations);
setField(newField, annotations);
public T parse(String name, Field field) {
T newField = newField(name, field);
setField(newField, field);
return newField;
}
protected void setField(T newField, Annotation[] annotations) {
protected void setField(T newField, Field field) {
if (field.getAnnotation(Column.class) != null) {
int length = field.getAnnotation(Column.class).length();
if (length != 0) {
newField.setLength(length);
}
} else if (field.getAnnotation(Array.class) != null) {
int length = field.getAnnotation(Array.class).length();
if (length != 0) {
newField.setLength(length);
}
}
}
......
package logwire.web.bo.field.parse;
import logwire.core.bo.annotation.Choice;
import logwire.core.bo.annotation.ForeignKey;
import logwire.core.bo.field.BizArray;
import logwire.core.bo.field.BizOne;
import logwire.core.exceptions.ApplicationException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.time.OffsetDateTime;
public abstract class FieldParserUtil {
......@@ -17,14 +21,30 @@ public abstract class FieldParserUtil {
* @param annotations
* @return
*/
public static FieldParser getParser(java.lang.reflect.Field field, Annotation[] annotations) {
return getParserByFieldType(field);
public static FieldParser getParser(java.lang.reflect.Field field) {
if (field.getAnnotation(Choice.class) != null) {
if (field.getType().equals(String.class)) {
return ChoiceFieldParser.getInstance();
} else if (field.getType().equals(BizArray.class)) {
return BizArrayFieldParser.getInstance();
} else {
throw new ApplicationException("@Choice 只能用与 String/BizArray 类型");
}
} else if (field.getAnnotation(ForeignKey.class) != null) {
//弱关联
if (field.getType().equals(BizOne.class)) {
return ForeignKeyFieldParser.getInstance();
} else {
throw new ApplicationException("@ForeignKey 只能用与 BizOne 类型");
}
}
return getParserByFieldType(field.getType());
}
private static FieldParser getParserByFieldType(java.lang.reflect.Field field) {
public static FieldParser getParserByFieldType(Type clazz) {
// 此时一定是存在 Field 类型的 annotation
// 根据字段类型来推断 Parser
Class clazz = field.getType();
if (clazz.equals(String.class)) {
return StringFieldParser.getInstance();
} else if (clazz.equals(Integer.class) || clazz.equals(int.class)) {
......@@ -41,7 +61,9 @@ public abstract class FieldParserUtil {
return DecimalFieldParser.getInstance();
} else if (clazz.equals(BizArray.class)) {
return BizArrayFieldParser.getInstance();
} else if (clazz.equals(BizOne.class)) {
return ForeignKeyFieldParser.getInstance();
}
return null;
throw new ApplicationException("该字段类型无法识别");
}
}
package logwire.web.bo.field.parse;
import logwire.core.bo.annotation.ForeignKey;
import logwire.core.bo.field.BizOne;
import logwire.core.exceptions.ApplicationException;
import logwire.core.meta.model.fields.ForeignKeyField;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ForeignKeyFieldParser extends FieldParser<ForeignKeyField> {
@Override
protected ForeignKeyField newField(String name, Field field) {
/**
*
* BizOne类型表示外键字段,
* TODO 若使用了@ForeignKey 弱关联
*
* */
if (field.getType().equals(BizOne.class)) {
if (field.getAnnotation(ForeignKey.class) != null) {
return new ForeignKeyField(name, field.getAnnotation(ForeignKey.class).referBoName());
} else {
Type genericType = field.getGenericType();
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
return new ForeignKeyField(name, actualTypeArgument.getTypeName());
}
} else {
throw new ApplicationException("非BizOne类型不能作为外键");
}
}
private ForeignKeyFieldParser() {
}
public static ForeignKeyFieldParser getInstance() {
return ForeignKeyFieldParser.SingletonHolder.instance;
}
private static class SingletonHolder {
private static ForeignKeyFieldParser instance = new ForeignKeyFieldParser();
}
}
......@@ -2,13 +2,12 @@ package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.IntegerField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class IntegerFieldParser extends FieldParser<IntegerField> {
@Override
protected IntegerField newField(Field field, Annotation[] annotations) {
return new IntegerField(field.getName());
protected IntegerField newField(String name, Field field) {
return new IntegerField(name);
}
private IntegerFieldParser() {
......
......@@ -2,13 +2,12 @@ package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.SmallIntegerField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class SmallIntegerFieldParser extends FieldParser<SmallIntegerField> {
@Override
protected SmallIntegerField newField(Field field, Annotation[] annotations) {
return new SmallIntegerField(field.getName());
protected SmallIntegerField newField(String name, Field field) {
return new SmallIntegerField(name);
}
private SmallIntegerFieldParser() {
......
......@@ -2,13 +2,12 @@ package logwire.web.bo.field.parse;
import logwire.core.meta.model.fields.StringField;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class StringFieldParser extends FieldParser<StringField> {
@Override
protected StringField newField(Field field, Annotation[] annotations) {
return new StringField(field.getName(), 50);
protected StringField newField(String name, Field field) {
return new StringField(name, 50);
}
private StringFieldParser() {
......
package logwire.web.bo.handler;
import logwire.core.bo.handler.TypeOperationHandler;
import logwire.web.bo.BoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CreateOperationHandler implements TypeOperationHandler {
@Autowired
BoService boService;
@Override
public Object execute(Class aClass, Object... args) {
return null;
public Object execute(Class clazz, Object... args) {
return boService.createBizObject(clazz);
}
@Override
......
package logwire.web.bo.loader;
import logwire.core.bo.annotation.BizModel;
import logwire.core.bo.annotation.Column;
import logwire.core.bo.annotation.*;
import logwire.core.bo.field.BizArray;
import logwire.core.bo.field.BizMany;
import logwire.core.bo.field.BizText;
import logwire.core.bo.object.BizObject;
import logwire.core.exceptions.ApplicationException;
import logwire.core.meta.model.Model;
import logwire.core.meta.model.fields.*;
import logwire.core.meta.query.IQuery;
import logwire.core.resource.BeanLoader;
import logwire.core.resource.loader.JavaModelBeanLoader;
......@@ -17,10 +20,11 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.io.DefaultResourceLoader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
......@@ -31,9 +35,9 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
/**
* load BoModel 的逻辑:
* 1、先遍历出所有BizObject的子类
* 2、将直接继承BizObject的类初始化
* 3、剩余的类中,判断是否独立的model(包含BizModel注解),若是,生成Model;若不是,字段添加至父类的Model
* 1、先遍历出所有 BizObject 的子类 得到集合
* 2、筛选出当中使用 @BizModel 的类,构建 Model,字段包含父类的字段
* 3、将集合中的剩余类的字段添加到父类对应的Model
*
* @param project 当前租户
* @param input 待加载的资源
......@@ -43,21 +47,23 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
@Override
public void load(TenantProject project, TenantProject input, Consumer<IQuery> consumer) throws Exception {
TenantClassLoader classLoader = project.getTenantBeanContext().getTenantClassLoader();
//先扫描到所有的 BizObject (BizObject的所有子类)
ClassPathScanningCandidateComponentProvider provider = loaderUtil.getScanningBeanProvider();
provider.setResourceLoader(new DefaultResourceLoader(classLoader));
provider.addIncludeFilter(loaderUtil.getAbstractTypeFilter(BizObject.class));
Set<BeanDefinition> beans = provider.findCandidateComponents("logwire.web.bo");
List<BeanDefinition> bizModelList = beans.stream().filter(beanDefinition -> {
try {
Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
BizModel bizModelAnnotation = clazz.getAnnotation(BizModel.class);
return bizModelAnnotation != null;
} catch (ClassNotFoundException e) {
throw new ApplicationException("");
}
}).collect(Collectors.toList());
Map<Boolean, List<BeanDefinition>> isBizModel = provider.findCandidateComponents("logwire.web")
.stream()
.collect(Collectors.groupingBy(beanDefinition -> {
try {
Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
BizModel bizModelAnnotation = clazz.getAnnotation(BizModel.class);
return bizModelAnnotation != null;
} catch (ClassNotFoundException e) {
throw new ApplicationException("");
}
}));
List<BeanDefinition> bizModelList = isBizModel.get(true);
for (BeanDefinition beanDefinition : bizModelList) {
Class<?> clazz = classLoader.loadClass(beanDefinition.getBeanClassName());
//独立model
......@@ -67,12 +73,7 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
model.setIncludeAuditFields(true);
model.setIncludeVersionField(true);
model.setIncludeDomainField(true);
initField(clazz, model);
/*
//todo
this.initIndex(clazz, model);
this.initSign(model);*/
initField(clazz, model, consumer);
consumer.accept(model);
}
......@@ -80,23 +81,105 @@ public class BoModelBeanLoader extends BeanLoader<IQuery, TenantProject> impleme
}
private void initField(Class<?> clazz, Model model) {
//获取所有带有Column注解的字段
private void initField(Class<?> clazz, Model model, Consumer consumer) {
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
Column column = f.getAnnotation(Column.class);
if (column != null) {
Annotation[] annotations = f.getDeclaredAnnotations();
FieldParser parser = FieldParserUtil.getParser(f, annotations);
if (parser == null) {
continue;
}
logwire.core.meta.model.fields.Field field = parser.parse(f, annotations);
if (f.getAnnotation(Column.class) != null) {
//带有Column注解的字段
FieldParser parser = FieldParserUtil.getParser(f);
logwire.core.meta.model.fields.Field field = parser.parse(f.getName(), f);
model.addField(field);
} else if (f.getAnnotation(Text.class) != null) {
// 带有Text注解的字段 大文本属性会创建一张子表(Model),子表名为:BO表名_属性名,一个BO有多个大字段时,使用同一张表
if (f.getType() != BizText.class) {
throw new ApplicationException("@Text 字段类型必须为BizText");
}
newTextModel(model, f, consumer);
} else if (f.getAnnotation(Array.class) != null) {
// 带有Text注解的字段 大文本属性会创建一张子表(Model),子表名为:BO表名_属性名,一个BO有多个大字段时,使用同一张表
if (f.getType() != BizArray.class) {
throw new ApplicationException("@Array 字段类型必须为BizArray");
}
newArrayModel(model, f, consumer);
} else if (f.getAnnotation(Many.class) != null) {
// 带有Text注解的字段 大文本属性会创建一张子表(Model),子表名为:BO表名_属性名,一个BO有多个大字段时,使用同一张表
if (f.getType() != BizMany.class) {
throw new ApplicationException("@Many 字段类型必须为BizMany");
}
newManyModel(model, f, consumer);
}
}
}
/**
* 数组字段值存到一个列中,用逗号分隔 字段:
* owner_id/所属对象ID (BigInt)
* value/值 (varchar/numeric/boolean/bigint/integer/timestamp)
* idx/顺序 Integer
*
* @param f
* @param consumer
*/
private void newArrayModel(Model model, Field f, Consumer consumer) {
Array array = f.getAnnotation(Array.class);
Model arrayModel = new Model();
arrayModel.setName(model.getName() + "_" + f.getName());
arrayModel.setVerboseName(array.label());
ForeignKeyField ownerId = new ForeignKeyField("owner_id", model.getName());
ownerId.setPrimaryKey(true);
arrayModel.addField(ownerId);
arrayModel.addField(new IntegerField("idx"));
Type actualTypeArguments = ((ParameterizedType) f.getGenericType()).getActualTypeArguments()[0];
FieldParser parser = FieldParserUtil.getParserByFieldType(actualTypeArguments);
logwire.core.meta.model.fields.Field valueField = parser.parse("value", f);
model.addField(valueField);
consumer.accept(model);
}
/**
* 大文本 字段:
* owner_id/所属对象ID (BigInt)
* field_name/字段名 varchar(50)
* value/值 (varchar/numeric/boolean/bigint/integer/timestamp)
*
* @param model
* @param f
* @param consumer
*/
private void newTextModel(Model model, Field f, Consumer consumer) {
Text text = f.getAnnotation(Text.class);
Model textModel = new Model();
textModel.setName(model.getName() + "_text");
textModel.setVerboseName(text.label());
ForeignKeyField ownerId = new ForeignKeyField("owner_id", model.getName());
ownerId.setPrimaryKey(true);
textModel.addField(ownerId);
textModel.addField(new StringField("field_name", 50));
textModel.addField(new TextField("value"));
consumer.accept(model);
}
/**
* 多对多关联属性 字段:
* id
* master_id 主表ID
* slave_id 从表ID
*
* @param model
* @param f
* @param consumer
*/
private void newManyModel(Model model, Field f, Consumer consumer) {
Many many = f.getAnnotation(Many.class);
Model manyModel = new Model();
manyModel.setName(model.getName() + "_" + f.getName());
manyModel.setVerboseName(many.label());
manyModel.addField(new AutoField());
manyModel.addField(new ForeignKeyField("master_id", model.getName()));
manyModel.addField(new ForeignKeyField("slave_id", many.referBoName()));
consumer.accept(model);
}
@Override
public boolean accept(TenantProject input) {
return true;
......
......@@ -14,6 +14,7 @@ import logwire.core.bo.handler.ObjectOperationHandler;
import logwire.core.bo.handler.OperationHandler;
import logwire.core.bo.handler.TypeOperationHandler;
import logwire.core.bo.object.BizObject;
import logwire.core.exceptions.ApplicationException;
import logwire.core.resource.BeanLoader;
import logwire.core.tenant.TenantClassLoader;
import logwire.core.tenant.TenantProject;
......@@ -31,24 +32,46 @@ import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@Component
public class BoRelationBeanDefinitionLoader extends BeanLoader<BoRelationDefinition, TenantProject> {
private final String BIZ_OBJECT = "biz_object";
private final String TYPE_OPERATION_PROVIDER = "type_operation_provider";
private final String OBJECT_OPERATION_PROVIDER = "object_operation_provider";
private final String LIST_OPERATION_PROVIDER = "list_operation_provider";
private final String TYPE_OPERATION_HANDLER = "type_operation_handler";
private final String OBJECT_OPERATION_HANDLER = "object_operation_handler";
private final String LIST_OPERATION_HANDLER = "list_operation_handler";
private final String TYPE_OPERATION_EVENT_HANDLER = "type_operation_event_handler";
private final String OBJECT_OPERATION_EVENT_HANDLER = "object_operation_event_handler";
private final String LIST_OPERATION_EVENT_HANDLER = "list_operation_event_handler";
@Autowired
QueryService queryService;
@Autowired
LoaderUtil loaderUtil;
/**
* 加载BO相关定义并初始化 service
*
* @param project 当前租户
* @param input 待加载的资源
* @param consumer 处理加载结果
* @throws Exception
*/
@Override
public void load(TenantProject project, TenantProject input, Consumer<BoRelationDefinition> consumer) throws Exception {
Map<String, BoRelationDefinition> boRelationBeanDefinitions = loadBeanDefinition(project);
boRelationBeanDefinitions.values().forEach(boRelationDefinition -> {
initializeService(boRelationDefinition, boRelationBeanDefinitions);
consumer.accept(boRelationDefinition);
});
}
......@@ -74,8 +97,7 @@ public class BoRelationBeanDefinitionLoader extends BeanLoader<BoRelationDefinit
field.set(null, o);
boRelationDefinition.setBoServiceInitialized(true);
} catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) {
//TODO
e.printStackTrace();
throw ApplicationException.wrap(e);
}
}
}
......@@ -91,45 +113,150 @@ public class BoRelationBeanDefinitionLoader extends BeanLoader<BoRelationDefinit
ClassPathScanningCandidateComponentProvider provider = loaderUtil.getScanningBeanProvider();
provider.setResourceLoader(new DefaultResourceLoader(classLoader));
addIncludeFilters(provider);
Set<BeanDefinition> boClassDefinitions = provider.findCandidateComponents("logwire.web.bo");
//beans 是有序的
for (BeanDefinition boClassDefinition : boClassDefinitions) {
Class<?> clazz = Class.forName(boClassDefinition.getBeanClassName(), true, classLoader);
if (loaderUtil.isBizObject(clazz)) {
BoRelationDefinition boRelationDefinition = doRegisterBeanDefinition((Class<? extends BizObject>) clazz);
boRelationBeanDefinitions.put(boRelationDefinition.getId(), boRelationDefinition);
} else {
//handler
if (loaderUtil.isOperationHandler(clazz)) {
if (!isConcrete((ScannedGenericBeanDefinition) boClassDefinition)) continue;
addOperationHandler(boRelationBeanDefinitions, (Class<OperationHandler>) clazz);
}
//event_handler
else if (loaderUtil.isOperationEventHandler(clazz)) {
if (!isConcrete((ScannedGenericBeanDefinition) boClassDefinition)) continue;
addOperationEventHandler(boRelationBeanDefinitions, (Class<OperationEventHandler>) clazz);
}
//operation
else if (clazz.getAnnotation(TypeOperationProvider.class) != null) {
Class<? extends BizObject> type = clazz.getAnnotation(TypeOperationProvider.class).type();
boRelationBeanDefinitions.get(type.getSimpleName()).addTypeOperationProvider(clazz);
} else if (clazz.getAnnotation(ObjectOperationProvider.class) != null) {
Class<? extends BizObject> type = clazz.getAnnotation(ObjectOperationProvider.class).type();
boRelationBeanDefinitions.get(type.getSimpleName()).addObjectOperationProvider(clazz);
} else if (clazz.getAnnotation(ListOperationProvider.class) != null) {
Class<? extends BizObject> type = clazz.getAnnotation(ListOperationProvider.class).type();
boRelationBeanDefinitions.get(type.getSimpleName()).addListOperationProvider(clazz);
}
}
}
// 在 logwire package 下获取所有 bo相关类(bizObject provider handler)
Set<BeanDefinition> boClassDefinitions = provider.findCandidateComponents("logwire.web");
Map<String, List<Class<?>>> beanClassMap = getGroupedMap(classLoader, boClassDefinitions);
registerBeanDefinition(boRelationBeanDefinitions, beanClassMap);
addOperationProvider(boRelationBeanDefinitions, beanClassMap);
addOperationHandler(boRelationBeanDefinitions, beanClassMap);
addOperationEventHandler(boRelationBeanDefinitions, beanClassMap);
return boRelationBeanDefinitions;
}
private Map<String, List<Class<?>>> getGroupedMap(TenantClassLoader classLoader, Set<BeanDefinition> boClassDefinitions) {
//集合拆分
return boClassDefinitions
.stream().map(beanDefinition -> {
try {
return Class.forName(beanDefinition.getBeanClassName(), true, classLoader);
} catch (ClassNotFoundException e) {
throw new ApplicationException(e.getMessage(), e);
}
}).collect(Collectors.groupingBy(clazz -> {
if (BizObject.class.isAssignableFrom(clazz)) {
return BIZ_OBJECT;
} else if (TypeOperationProvider.class.isAssignableFrom(clazz)) {
return TYPE_OPERATION_PROVIDER;
} else if (ObjectOperationProvider.class.isAssignableFrom(clazz)) {
return OBJECT_OPERATION_PROVIDER;
} else if (ListOperationProvider.class.isAssignableFrom(clazz)) {
return LIST_OPERATION_PROVIDER;
} else if (TypeOperationHandler.class.isAssignableFrom(clazz)) {
return TYPE_OPERATION_HANDLER;
} else if (ObjectOperationHandler.class.isAssignableFrom(clazz)) {
return OBJECT_OPERATION_HANDLER;
} else if (ListOperationHandler.class.isAssignableFrom(clazz)) {
return LIST_OPERATION_HANDLER;
} else if (TypeOperationEventHandler.class.isAssignableFrom(clazz)) {
return TYPE_OPERATION_EVENT_HANDLER;
} else if (ObjectOperationEventHandler.class.isAssignableFrom(clazz)) {
return OBJECT_OPERATION_EVENT_HANDLER;
} else if (ListOperationEventHandler.class.isAssignableFrom(clazz)) {
return LIST_OPERATION_EVENT_HANDLER;
}
return null;
}));
}
private void registerBeanDefinition(Map<String, BoRelationDefinition> boRelationBeanDefinitions, Map<String, List<Class<?>>> beanClassMap) {
beanClassMap.get(BIZ_OBJECT).forEach(clazz -> {
BoRelationDefinition boRelationDefinition = doRegisterBeanDefinition((Class<? extends BizObject>) clazz);
boRelationBeanDefinitions.put(boRelationDefinition.getId(), boRelationDefinition);
});
}
private void addOperationProvider(Map<String, BoRelationDefinition> boRelationBeanDefinitions, Map<String, List<Class<?>>> beanClassMap) {
beanClassMap.get(TYPE_OPERATION_PROVIDER).forEach(clazz -> {
Class<? extends BizObject> type = clazz.getAnnotation(TypeOperationProvider.class).type();
boRelationBeanDefinitions.get(type.getSimpleName()).addTypeOperationProvider(clazz);
});
beanClassMap.get(OBJECT_OPERATION_PROVIDER).forEach(clazz -> {
Class<? extends BizObject> type = clazz.getAnnotation(ObjectOperationProvider.class).type();
boRelationBeanDefinitions.get(type.getSimpleName()).addObjectOperationProvider(clazz);
});
beanClassMap.get(LIST_OPERATION_PROVIDER).forEach(clazz -> {
Class<? extends BizObject> type = clazz.getAnnotation(ListOperationProvider.class).type();
boRelationBeanDefinitions.get(type.getSimpleName()).addListOperationProvider(clazz);
});
}
private void addOperationHandler(Map<String, BoRelationDefinition> boRelationBeanDefinitions, Map<String, List<Class<?>>> beanClassMap) {
beanClassMap.get(TYPE_OPERATION_HANDLER).forEach(clazz -> {
try {
//get BizObject from genericInterface
BoRelationDefinition boRelationDefinition = getBoRelationDefinitionFromGeneric(boRelationBeanDefinitions, clazz);
TypeOperationHandler opHandler = (TypeOperationHandler) clazz.newInstance();
boRelationDefinition.getTypeOperationHandlers().add(opHandler);
} catch (IllegalAccessException | InstantiationException e) {
throw ApplicationException.wrap(e);
}
});
beanClassMap.get(OBJECT_OPERATION_HANDLER).forEach(clazz -> {
try {
//get BizObject from genericInterface
BoRelationDefinition boRelationDefinition = getBoRelationDefinitionFromGeneric(boRelationBeanDefinitions, clazz);
ObjectOperationHandler opHandler = (ObjectOperationHandler) clazz.newInstance();
boRelationDefinition.getObjectOperationHandlers().add(opHandler);
} catch (IllegalAccessException | InstantiationException e) {
throw ApplicationException.wrap(e);
}
});
beanClassMap.get(LIST_OPERATION_HANDLER).forEach(clazz -> {
try {
//get BizObject from genericInterface
BoRelationDefinition boRelationDefinition = getBoRelationDefinitionFromGeneric(boRelationBeanDefinitions, clazz);
ListOperationHandler opHandler = (ListOperationHandler) clazz.newInstance();
boRelationDefinition.getListOperationHandlers().add(opHandler);
} catch (IllegalAccessException | InstantiationException e) {
throw ApplicationException.wrap(e);
}
});
}
private void addOperationEventHandler(Map<String, BoRelationDefinition> boRelationBeanDefinitions, Map<String, List<Class<?>>> beanClassMap) {
beanClassMap.get(TYPE_OPERATION_EVENT_HANDLER).forEach(clazz -> {
try {
BoRelationDefinition boRelationDefinition = getBoRelationDefinitionFromGeneric(boRelationBeanDefinitions, clazz);
List<TypeOperationEventHandler> typeOperationEventHandlers = boRelationDefinition.getTypeOperationEventHandlers();
TypeOperationEventHandler opHandler = (TypeOperationEventHandler) clazz.newInstance();
typeOperationEventHandlers.add(opHandler);
} catch (IllegalAccessException | InstantiationException e) {
throw ApplicationException.wrap(e);
}
});
beanClassMap.get(OBJECT_OPERATION_EVENT_HANDLER).forEach(clazz -> {
try {
//get BizObject from genericInterface
BoRelationDefinition boRelationDefinition = getBoRelationDefinitionFromGeneric(boRelationBeanDefinitions, clazz);
ObjectOperationEventHandler opHandler = (ObjectOperationEventHandler) clazz.newInstance();
boRelationDefinition.getObjectOperationEventHandlers().add(opHandler);
} catch (IllegalAccessException | InstantiationException e) {
throw ApplicationException.wrap(e);
}
});
beanClassMap.get(LIST_OPERATION_EVENT_HANDLER).forEach(clazz -> {
try {
//get BizObject from genericInterface
BoRelationDefinition boRelationDefinition = getBoRelationDefinitionFromGeneric(boRelationBeanDefinitions, clazz);
ListOperationEventHandler opHandler = (ListOperationEventHandler) clazz.newInstance();
boRelationDefinition.getListOperationEventHandlers().add(opHandler);
} catch (IllegalAccessException | InstantiationException e) {
throw ApplicationException.wrap(e);
}
});
}
private BoRelationDefinition getBoRelationDefinitionFromGeneric(Map<String, BoRelationDefinition> boRelationBeanDefinitions, Class<?> clazz) {
//get BizObject from genericInterface
Class<? extends BizObject> bizObject = (Class<? extends BizObject>) ((ParameterizedType) clazz.getGenericInterfaces()[0]).getActualTypeArguments()[0];
return boRelationBeanDefinitions.get(bizObject.getSimpleName());
}
private BoRelationDefinition doRegisterBeanDefinition(Class<? extends BizObject> beanClass) {
BoRelationDefinition boRelationDefinition = new BoRelationDefinition();
boRelationDefinition.setId(beanClass.getSimpleName());
boRelationDefinition.setName(beanClass.getSimpleName());
boRelationDefinition.setId(beanClass.getName());
boRelationDefinition.setName(beanClass.getName());
boRelationDefinition.setBoClass(beanClass);
boRelationDefinition.setBizModel(beanClass.isAnnotationPresent(BizModel.class));
return boRelationDefinition;
......@@ -145,38 +272,6 @@ public class BoRelationBeanDefinitionLoader extends BeanLoader<BoRelationDefinit
provider.addIncludeFilter(new AnnotationTypeFilter(ListOperationProvider.class));
}
private void addOperationEventHandler(Map<String, BoRelationDefinition> bizObjectBeanMap, Class<OperationEventHandler> clazz) throws IllegalAccessException, InstantiationException {
//get BizObject from genericInterface
Class<? extends BizObject> bizObject = (Class<? extends BizObject>) ((ParameterizedType) clazz.getGenericInterfaces()[0]).getActualTypeArguments()[0];
BoRelationDefinition boRelationDefinition = bizObjectBeanMap.get(bizObject.getSimpleName());
OperationEventHandler opEventHandler = clazz.newInstance();
if (opEventHandler.isEnabled()) {
if (TypeOperationEventHandler.class.isAssignableFrom(clazz)) {
boRelationDefinition.getTypeOperationEventHandlers().add((TypeOperationEventHandler) opEventHandler);
} else if (TypeOperationHandler.class.isAssignableFrom(clazz)) {
boRelationDefinition.getObjectOperationEventHandlers().add((ObjectOperationEventHandler) opEventHandler);
} else {
boRelationDefinition.getListOperationEventHandlers().add((ListOperationEventHandler) opEventHandler);
}
}
}
private void addOperationHandler(Map<String, BoRelationDefinition> bizObjectBeanMap, Class<OperationHandler> clazz) throws IllegalAccessException, InstantiationException {
//get BizObject from genericInterface
Class<? extends BizObject> bizObject = (Class<? extends BizObject>) ((ParameterizedType) clazz.getGenericInterfaces()[0]).getActualTypeArguments()[0];
BoRelationDefinition boRelationDefinition = bizObjectBeanMap.get(bizObject.getSimpleName());
OperationHandler opHandler = clazz.newInstance();
if (opHandler.isEnabled()) {
if (TypeOperationHandler.class.isAssignableFrom(clazz)) {
boRelationDefinition.getTypeOperationHandlers().add((TypeOperationHandler) opHandler);
} else if (ObjectOperationHandler.class.isAssignableFrom(clazz)) {
boRelationDefinition.getObjectOperationHandlers().add((ObjectOperationHandler) opHandler);
} else if (ListOperationHandler.class.isAssignableFrom(clazz)) {
boRelationDefinition.getListOperationHandlers().add((ListOperationHandler) opHandler);
}
}
}
private boolean isConcrete(ScannedGenericBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isConcrete();
}
......
......@@ -2,6 +2,7 @@ package logwire.web.bo.loader;
import logwire.core.bo.eventhandler.OperationEventHandler;
import logwire.core.bo.handler.OperationHandler;
import logwire.core.bo.handler.TypeOperationHandler;
import logwire.core.bo.object.BizObject;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
......@@ -26,10 +27,18 @@ public class LoaderUtil {
}
public boolean isAssignableFrom(Class<?> beanClass) {
return BizObject.class.isAssignableFrom(beanClass);
}
public boolean isBizObject(Class<?> beanClass) {
return BizObject.class.isAssignableFrom(beanClass);
}
public boolean isTypeOperationHandler(Class<?> beanClass) {
return TypeOperationHandler.class.isAssignableFrom(beanClass);
}
public boolean isOperationHandler(Class<?> beanClass) {
return OperationHandler.class.isAssignableFrom(beanClass);
}
......@@ -57,6 +66,12 @@ public class LoaderUtil {
super(useDefaultFilters);
}
/**
*
* //TODO 注释
* @param beanDefinition
* @return
*/
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
......
package logwire.web.bo.provider;
import logwire.core.bo.annotation.ObjectOperationProvider;
import logwire.core.bo.annotation.Operation;
import logwire.core.bo.object.BizObject;
//所有BO Object 默认Operation定义
@ObjectOperationProvider(type = BizObject.class)
public interface DefaultObjectOperationProvider {
@Operation()
void save();
@Operation()
void delete();
@Operation()
void update(String... fields);
// 更多操作定义
}
\ No newline at end of file
......@@ -15,7 +15,7 @@ public interface DefaultTypeOperationProvider {
<X> X create();
@Operation()
<X> X create(Map defaultValues);
<X> X createWithDefault(Map defaultValues);
@Operation()
<X> X create(String query);
......@@ -42,7 +42,7 @@ public interface DefaultTypeOperationProvider {
<X extends BizObject> BizList<X> createList(Map fields);
@Operation()
<X extends BizObject> BizList<X> findAll(Map fields);
<X extends BizObject, T extends BizList<X>> T findAll(Map fields);
@Operation()
<X extends BizObject> BizList<X> findAll(String query);
......
package logwire.web.bo.proxy;
import logwire.core.bo.handler.Handler;
import logwire.core.bo.object.BizObject;
import logwire.web.bo.BoRelationDefinition;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.SuperMethod;
import net.bytebuddy.implementation.bind.annotation.This;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
public class ObjectOperationInterceptor {
private static final Logger logger = LoggerFactory.getLogger(TypeOperationInterceptor.class);
private BoRelationDefinition boRelationDefinition;
public ObjectOperationInterceptor(BoRelationDefinition boRelationDefinition) {
this.boRelationDefinition = boRelationDefinition;
}
public Object interceptor(@This Object proxy, @Origin Method method,
@SuperMethod Method superMethod,
@AllArguments Object[] args) throws Exception {
if (superMethod != null) {
return superMethod.invoke(boRelationDefinition.getBoClass().getSuperclass().getField("service"), args);
}
return doHandler(method, args);
}
/**
* 根据methodName执行对应的handler
*/
private Object doHandler(Method method, Object[] args) {
Class<? extends BizObject> bizClazz = boRelationDefinition.getBoClass();
String operationName = method.getName();
logger.debug("Execute operation {} start", new Object[]{operationName});
getHandler(operationName, boRelationDefinition.getTypeOperationEventHandlers(),
typeOperationEventHandler -> !typeOperationEventHandler.isAfter())
.doBefore(bizClazz, args);
Object result = getHandler(operationName, boRelationDefinition.getTypeOperationHandlers(),
typeOperationHandler -> typeOperationHandler.accept(bizClazz, args))
.execute(bizClazz, args);
getHandler(operationName, boRelationDefinition.getTypeOperationEventHandlers(),
typeOperationEventHandler -> typeOperationEventHandler.isAfter())
.doAfter(bizClazz, result, args);
return result;
}
private <T extends Handler> T getHandler(String operation, List<T> handlers, Function<T, Boolean> function) {
return handlers.stream()
.filter(handler -> operation.equals(handler.getOperation()) && function.apply(handler))
.max(Comparator.comparing(T::getOrder)).get();
}
}
package logwire.web.bo.proxy;
import com.google.common.collect.Lists;
import logwire.core.bo.handler.ObjectOperationHandler;
import logwire.core.bo.object.BizObject;
import logwire.web.bo.BoRelationDefinition;
import logwire.web.bo.provider.DefaultTypeOperationProvider;
......@@ -7,9 +9,11 @@ import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import java.util.List;
import java.util.Map;
public class Proxy {
/**
*
* 初始化 BO的 service : TypeOperationProvider
*
* @param boRelationDefinition
......@@ -19,21 +23,41 @@ public class Proxy {
* @throws NoSuchFieldException
*/
public static Object createTypeOperationProvider(BoRelationDefinition boRelationDefinition) throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class<? extends BizObject> beanClass = boRelationDefinition.getBoClass();
Class<? extends BizObject> boClass = boRelationDefinition.getBoClass();
// 动态生成service
// 若直接继承了BizObject,则动态代理继承DefaultTypeOperationProvider,否则继承父类中的service对应的TypeOperationProvider
// 若直接继承了BizObject,则动态代理继承DefaultTypeOperationProvider,
// 否则继承父类中的service对应的TypeOperationProvider
Class superClass = DefaultTypeOperationProvider.class;
if (beanClass.getSuperclass() != BizObject.class) {
if (boClass.getSuperclass() != BizObject.class) {
// parent TypeOperationProvider
superClass = beanClass.getSuperclass().getField("serivce").getClass();
superClass = boClass.getSuperclass().getField("service").getClass();
}
return new ByteBuddy().subclass(superClass)
.implement(boRelationDefinition.getTypeOperationProviders())
.method(ElementMatchers.any())
.intercept(MethodDelegation.to(new TypeOperationInterceptor(boRelationDefinition)))
.make()
.load(beanClass.getClassLoader())
.load(boClass.getClassLoader())
.getLoaded().newInstance();
}
public static Object createObjectOperationProvider(BoRelationDefinition boRelationDefinition, Map<String, BoRelationDefinition> boRelationDefinitions) throws IllegalAccessException, InstantiationException {
Class<? extends BizObject> boClass = boRelationDefinition.getBoClass();
Class boSuperClass = boClass.getSuperclass();
List<ObjectOperationHandler> interfaces = Lists.newArrayList(boRelationDefinition.getObjectOperationHandlers());
while (boSuperClass != BizObject.class) {
interfaces.addAll(boRelationDefinitions.get(boSuperClass.getName()).getObjectOperationHandlers());
boSuperClass = boSuperClass.getSuperclass();
}
return new ByteBuddy().subclass(boClass.getSuperclass())
.implement(boRelationDefinition.getObjectOperationProviders())
.method(ElementMatchers.any())
.intercept(MethodDelegation.to(new ObjectOperationInterceptor(boRelationDefinition)))
.make()
.load(boClass.getClassLoader())
.getLoaded().newInstance();
}
}
......@@ -32,7 +32,7 @@ public class TypeOperationInterceptor {
@SuperMethod Method superMethod,
@AllArguments Object[] args) throws Exception {
if (superMethod != null) {
return superMethod.invoke(proxy, args);
return superMethod.invoke(boRelationDefinition.getBoClass().getSuperclass().getField("service"), args);
}
return doHandler(method, args);
}
......@@ -62,7 +62,7 @@ public class TypeOperationInterceptor {
private <T extends Handler> T getHandler(String operation, List<T> handlers, Function<T, Boolean> function) {
return handlers.stream()
.filter(handler -> operation.equals(handler.getOperation()) && function.apply(handler))
.max(Comparator.comparing(T::getOrder)).get();
.min(Comparator.comparing(T::getOrder)).get();
}
}
......
......@@ -159,10 +159,10 @@ public class Session {
for (int i = 0; i < this.bizObjects.size(); i++) {
BizObject t = this.bizObjects.get(i);
if (QueryTransactionCode.TX_INSERT.equals(t.getTxCode())) {
List<BizObject> list = insertBizObjects.get(t.getModelName());
List<BizObject> list = insertBizObjects.get(t.getBoName());
if (list == null) {
list = Lists.newArrayList();
insertBizObjects.put(t.getModelName(), list);
insertBizObjects.put(t.getBoName(), list);
}
list.add(t);
} else {
......@@ -197,14 +197,14 @@ public class Session {
}
otherBizObjects.clear();
}
logwire.web.biz.session.SessionHolder.clear();
SessionHolder.clear();
}
private void persistedHeader(BizObject t, QueryService queryService, PersistedRecorder persistedRecorder) {
//明细表有增删改时,头表一定要修改(如果不是新增的头表)而不管主表的数据是否有变化
Map<String, Set<BizObject>> headers = itemHeaderRelations.get(t.getModelName());
Map<String, Set<BizObject>> headers = itemHeaderRelations.get(t.getBoName());
if (headers != null && !headers.isEmpty()) {
Set<BizObject> set = headers.get(t.getPkValue());
Set<BizObject> set = headers.get(t.getId());
if (set == null || set.isEmpty()) {
return;
}
......@@ -222,12 +222,10 @@ public class Session {
private void persistedInsert(BizObject t, QueryService queryService, PersistedRecorder persistedRecorder) {
BizObjectAgent agent = getOperableAgent(t);
TenantUser currentUser = SecurityUtil.currentUser();
if (BizObjectStatus.NEW_SAVE.equals(t.getBizObjectStatus())) {
if (BizObjectStatus.NEW_SAVE.equals(t.getTxCode())) {
agent.setInternal(QueryTransactionCode.TX_FIELD_NAME, QueryTransactionCode.TX_INSERT);
// persistedBefore(t, itemHeaderRelations, queryService); TODO 新增明细表前先新增主表
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_INSERT_BEFORE.name(), currentUser.getDomain(), t);
queryService.insert(t.getModelName(), t.toMap());
actionContext.emit(t.getOperableName(), BuiltinEventNames.BIZ_INSERT_AFTER.name(), currentUser.getDomain(), t);
queryService.insert(t.getBoName(), t.toMap());
persistedRecorder.accept(t);
persistedHeader(t, queryService, persistedRecorder);
}
......@@ -351,15 +349,15 @@ public class Session {
* @param fieldName
*/
public void cache(BizObject t, String fieldName) {
Object pkValue = t.getPkValue();
Object pkValue = t.getId();
if (pkValue == null) {
return;
}
//拿到存放某个 model 的主键缓存值的 map
Map<String, Map<String, Set<Object>>> modelMap = pkCache.get(t.getModelName());
Map<String, Map<String, Set<Object>>> modelMap = pkCache.get(t.getBoName());
if (modelMap == null) {
modelMap = Maps.newHashMap();
pkCache.put(t.getModelName(), modelMap);
pkCache.put(t.getBoName(), modelMap);
}
//拿到存放通过某个 model 的 某个字段查询得到的主键后缓存值的 map
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment