diff --git a/pom.xml b/pom.xml
index 5c39704c33e61a14d6511df0ac7fae5999f8f8aa..aaa2e70c5750a0132d906ba6cda57871c5ddd5a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
schbrain-canal
- 1.0.0-RELEASE
+ 1.1.0-SNAPSHOT
diff --git a/schbrain-canal-client/pom.xml b/schbrain-canal-client/pom.xml
index 965c387ab9367b676c5c70a4111b53222b85ff0f..64075e4d2b1f3e384d88e05127702fc63f0096cf 100644
--- a/schbrain-canal-client/pom.xml
+++ b/schbrain-canal-client/pom.xml
@@ -23,6 +23,11 @@
canal.protocol
1.1.5
+
+ joda-time
+ joda-time
+ 2.9.4
+
com.schbrain.framework
schbrain-spring-support
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/CanalEventListener.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/CanalEventListener.java
index 959123f0030ffbcce6263ae7165ae6588f2f69c4..61b69247875d053d83e5a383bbd8925f4c8b7ae7 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/CanalEventListener.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/CanalEventListener.java
@@ -12,6 +12,10 @@ import java.lang.annotation.*;
@Component
public @interface CanalEventListener {
+ /**
+ * bean name
+ * @return
+ */
@AliasFor(annotation = Component.class)
String value() default "";
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/DeleteListenPoint.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/DeleteListenPoint.java
index 4e367d51233572e742fafed445ad9a75f897f2e4..96e9afe5eacfe1c65abdeecf53e4745e1cdea7f6 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/DeleteListenPoint.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/DeleteListenPoint.java
@@ -7,11 +7,9 @@ import java.lang.annotation.*;
/**
* ListenPoint for delete
- *
- * @author chen.qian
- * @date 2018/3/19
+ * @author zhuyf
+ * @date 2022/06/19
*/
-
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/InsertListenPoint.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/InsertListenPoint.java
index 6f8f6b04a6c10938e1424e5b096ebb9385055a07..4e9d284ca873c1635f74e7cb16689a0176ce98a6 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/InsertListenPoint.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/InsertListenPoint.java
@@ -6,12 +6,10 @@ import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**
- * ListenPoint for insert
- *
- * @author chen.qian
- * @date 2018/3/19
+ * ListenPoint for inster
+ * @author zhuyf
+ * @date 2022/06/19
*/
-
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/ListenPoint.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/ListenPoint.java
index 1cfb7f5ed02e2442185aa5b15b6443eaccd6a4ce..ca45ed72f1e79feb354dd8d8dad15ca3fccfd69f 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/ListenPoint.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/ListenPoint.java
@@ -6,12 +6,9 @@ import java.lang.annotation.*;
/**
* used to indicate that method(or methods) is(are) the candidate of the
- * canal event distributor
- *
- * @author chen.qian
- * @date 2018/3/19
+ * @author zhuyf
+ * @date 2022/06/19
*/
-
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/TableFilter.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/TableFilter.java
index 82409a1626486adaa1081fd6c301a637c3062bf4..e3d2f4daa1b613524a427d5b966a1be25e317eab 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/TableFilter.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/TableFilter.java
@@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Table
+ * table filter
* @author zhuyf
* @date 2022/6/16
*/
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/UpdateListenPoint.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/UpdateListenPoint.java
index f779c3fa97958dab56f0e9b06c39dfdee9e44cd3..4ad56b4290586be147a0db3dac571f5c8e200ec6 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/UpdateListenPoint.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/annotation/UpdateListenPoint.java
@@ -7,11 +7,9 @@ import java.lang.annotation.*;
/**
* ListenPoint for update
- *
- * @author chen.qian
- * @date 2018/3/19
+ * @author zhuyf
+ * @date 2022/06/19
*/
-
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/conf/MethodArgumentConfig.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/conf/MethodArgumentConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d5faad50922967d28e18c19809b527e254660d5
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/conf/MethodArgumentConfig.java
@@ -0,0 +1,12 @@
+package com.schbrain.canal.client.conf;
+
+import com.schbrain.canal.client.core.MethodArgumentResolver;
+
+/**
+ * @author zhuyf
+ * @date 2022/6/22
+ */
+public class MethodArgumentConfig {
+
+ public static MethodArgumentResolver LISTENERMETHODARGUMENTRESOLVER = new MethodArgumentResolver();
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/EditMetaInfo.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/EditMetaInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..f80c910ebe41fe3b70f03ae97dc667f55ae25c0d
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/EditMetaInfo.java
@@ -0,0 +1,20 @@
+package com.schbrain.canal.client.core;
+
+import lombok.Data;
+
+/**
+ * 用于封装修改数据的
+ * @author zhuyf
+ * @date 2022/6/22
+ */
+@Data
+public class EditMetaInfo {
+ /**
+ * 修改后
+ */
+ private Object after;
+ /**
+ * 修改前
+ */
+ private Object before;
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/HandlerConf.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/HandlerConf.java
index ad01bdd943369133202be01c7fb66554438b4c2b..4ea6f1a72a723399cfb35fbff250c2a177bace24 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/HandlerConf.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/HandlerConf.java
@@ -1,6 +1,7 @@
package com.schbrain.canal.client.core;
import com.schbrain.canal.client.event.CanalEvent;
+import com.schbrain.canal.client.event.ResolverCanalEvent;
import lombok.Data;
import lombok.Getter;
import lombok.experimental.Accessors;
@@ -29,9 +30,12 @@ public class HandlerConf {
*/
private final List annoListeners;
- public HandlerConf(List listeners, Map> tableCanalEventMap, List annoListeners) {
+ private final Map>> resolverCanalEvents;
+
+ public HandlerConf(List listeners, Map> tableCanalEventMap, List annoListeners,Map>> resolverCanalEvents) {
this.listeners = listeners;
this.tableCanalEventMap = tableCanalEventMap;
this.annoListeners = annoListeners;
+ this.resolverCanalEvents = resolverCanalEvents;
}
}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/MethodArgumentResolver.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/MethodArgumentResolver.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f8174a831633b1b34d62a8884a64fdb2d180b0c
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/MethodArgumentResolver.java
@@ -0,0 +1,145 @@
+package com.schbrain.canal.client.core;
+
+import com.schbrain.canal.client.event.ResolverCanalEvent;
+import com.schbrain.canal.client.exception.CanalClientException;
+import com.schbrain.canal.client.exception.ReflectionException;
+import com.schbrain.canal.client.reflector.DefaultReflectorFactory;
+import com.schbrain.canal.client.reflector.Reflector;
+import com.schbrain.canal.client.reflector.ReflectorFactory;
+import com.schbrain.canal.client.reflector.DefaultObjectFactory;
+import com.schbrain.canal.client.transfer.ObjectFactory;
+import com.schbrain.canal.client.type.TypeHandler;
+import com.schbrain.canal.client.type.TypeHandlerRegister;
+import com.schbrain.canal.client.utils.Dml;
+import com.schbrain.canal.client.utils.MapUnderscoreToCamelCase;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.text.ParseException;
+import java.util.*;
+
+/**
+ * @author zhuyf
+ * @date 2022/6/21
+ */
+@Slf4j
+public class MethodArgumentResolver {
+
+ public static Map classNameMappingClass = new HashMap<>();
+
+ private ObjectFactory objectFactory = new DefaultObjectFactory();
+
+ private ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
+
+ /**
+ * 获取参数类
+ * @param event
+ * @return
+ */
+ public Class getArgumentClass(ResolverCanalEvent> event) {
+ if (!classNameMappingClass.containsKey(event)) {
+ //接口泛型缓存
+ boolean cache = interfaceGeneric(event);
+ if(!cache){
+ //继承类泛型缓存
+ cache = extendGeneric(event);
+ }
+ if(!cache){
+ CanalClientException e = new CanalClientException(event.getClass() + "generic get exception");
+ log.error("generic get exception",e);
+ throw e;
+ }
+ }
+ return classNameMappingClass.get(event);
+ }
+
+
+ /**
+ * 接口泛型缓存
+ * @param event
+ * @return
+ */
+ private boolean interfaceGeneric(ResolverCanalEvent> event){
+ Type[] types = event.getClass().getGenericInterfaces();
+ if(types == null || types.length == 0){
+ return false;
+ }
+ for (Type type : types) {
+ if(!(type instanceof ParameterizedType)){
+ continue;
+ }
+ ParameterizedType parameterized = (ParameterizedType)type;
+ Type rawType = parameterized.getRawType();
+ if(rawType.equals(ResolverCanalEvent.class)){
+ Class clazz = (Class)parameterized.getActualTypeArguments()[0];
+ classNameMappingClass.put(event, clazz);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean extendGeneric(ResolverCanalEvent> event){
+ Class c = event.getClass();
+ while(true){
+ Type type = c.getGenericSuperclass();
+ if(type instanceof ParameterizedType){
+ ParameterizedType parameterizedType = (ParameterizedType)type;
+ Type[] types = parameterizedType.getActualTypeArguments();
+ if(types!= null && types.length>0){
+ classNameMappingClass.put(event, (Class) types[0]);
+ return true;
+ }
+ }
+ c = c.getSuperclass();
+ if(type.equals(Object.class)){
+ break;
+ }
+ }
+ return false;
+ }
+
+ public List resolver(ResolverCanalEvent event, Dml dml) throws InvocationTargetException, IllegalAccessException, ParseException,ReflectionException {
+ EditMetaInfo metaInfo = new EditMetaInfo();
+ Class c = getArgumentClass(event);
+ List editMetaInfos=new ArrayList<>();
+ List datas = dml.getData();
+ for (Dml.Row row : datas) {
+ Object after = columnsConvertObject(c,row.getData());
+ metaInfo.setAfter(after);
+ Object before = columnsConvertObject(c,row.getOld());
+ metaInfo.setBefore(before);
+ editMetaInfos.add(metaInfo);
+ }
+ return editMetaInfos;
+ }
+
+
+ public Object columnsConvertObject(Class c,Map columns) throws ReflectionException, InvocationTargetException, IllegalAccessException, ParseException {
+ if(columns==null||columns.isEmpty()){
+ return null;
+ }
+ Reflector classesReflector= reflectorFactory.findForClass(c);
+ Object o = objectFactory.create(c);
+ for (String columnName: columns.keySet()) {
+ String filedName= MapUnderscoreToCamelCase.convertByCache(columnName);
+ Object value=columns.get(columnName);
+ if(value==null){
+ continue;
+ }
+ if (!classesReflector.hasGetter(filedName)) {
+ continue;
+ }
+ Type setterType= classesReflector.getSetterType(filedName);
+ TypeHandler typeHandler= TypeHandlerRegister.getTypeHandler(setterType);
+ if(typeHandler==null){
+ log.error("未适配到typeHandle{},name:{},value:{},",setterType,filedName,value);
+ }
+ classesReflector.getSetInvoker(filedName).invoke(o,new Object[]{typeHandler.convert(value)});
+ }
+ return o;
+ }
+
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/SimpleCanalClient.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/SimpleCanalClient.java
index 44419802fcf908a9e7239118f2641d83b111b794..a56abcb4da490696406f631e71b7d293478aa949 100644
--- a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/SimpleCanalClient.java
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/core/SimpleCanalClient.java
@@ -5,17 +5,16 @@ import com.schbrain.canal.client.annotation.CanalEventListener;
import com.schbrain.canal.client.annotation.ListenPoint;
import com.schbrain.canal.client.annotation.TableFilter;
import com.schbrain.canal.client.conf.CanalClientConfig;
+import com.schbrain.canal.client.conf.MethodArgumentConfig;
import com.schbrain.canal.client.conf.SchbrainCanalConfig;
import com.schbrain.canal.client.event.CanalEvent;
+import com.schbrain.canal.client.event.ResolverCanalEvent;
import com.schbrain.canal.client.transfer.TransponderFactory;
import com.schbrain.canal.client.utils.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
-import org.springframework.core.annotation.AnnotationUtils;
-
-import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
@@ -36,6 +35,9 @@ public class SimpleCanalClient extends AbstractCanalClient {
* 所有执行器
*/
private final List listeners = new ArrayList<>();
+
+ //解析器事件
+ private final Map>> resolverCanalEvents = new HashMap<>();
/**
* 表过滤器
*/
@@ -53,46 +55,96 @@ public class SimpleCanalClient extends AbstractCanalClient {
private void initListeners() {
log.info("{}: initializing the listeners....", Thread.currentThread().getName());
+ //初始接口监听器
+ initEventList();
+ //初始注解监听器
+ initAnnotionList();
+ //初始解析器
+ initResolverList();
+ log.info("{}: initializing the listeners end.", Thread.currentThread().getName());
+ if (log.isWarnEnabled() && listeners.isEmpty() && annoListeners.isEmpty()) {
+ log.warn("{}: No listener found in context! ", Thread.currentThread().getName());
+ }
+ }
+
+ /**
+ * 初始事件监听器
+ */
+ private void initEventList(){
List list = BeanUtil.getBeansOfType(CanalEvent.class);
- if(list!=null && list.size() > 0){
- List unFilters = new ArrayList<>();
- for (CanalEvent canalEvent : list) {
- TableFilter filter = canalEvent.getClass().getAnnotation(TableFilter.class);
- if(filter!=null && StringUtils.isNotBlank(filter.schame()) && StringUtils.isNotBlank(filter.table())){
- String key = filter.schame()+":"+filter.table();
- List filterList = MapUtils.getObject(tableCanalEventMap,key,new ArrayList<>());
- filterList.add(canalEvent);
+ if(list==null || list.size()<=0){
+ return;
+ }
+ List unFilters = new ArrayList<>();
+ for (CanalEvent canalEvent : list) {
+ Class>[] classes = canalEvent.getClass().getInterfaces();
+ for (Class aClass : classes) {
+ if(ResolverCanalEvent.class.equals(aClass)){
continue;
}
- unFilters.add(canalEvent);
}
- if(unFilters!=null && unFilters.size()>0){
- listeners.addAll(unFilters);
+ TableFilter filter = canalEvent.getClass().getAnnotation(TableFilter.class);
+ if(filter!=null && StringUtils.isNotBlank(filter.schame()) && StringUtils.isNotBlank(filter.table())){
+ String key = filter.schame()+":"+filter.table();
+ List filterList = MapUtils.getObject(tableCanalEventMap,key,new ArrayList<>());
+ filterList.add(canalEvent);
+ continue;
}
+ unFilters.add(canalEvent);
}
+ if(unFilters!=null && unFilters.size()>0){
+ listeners.addAll(unFilters);
+ }
+ }
+
+ /**
+ * 初始注解监听器
+ */
+ private void initAnnotionList(){
Map listenerMap = BeanUtil.getBeansWithAnnotation(CanalEventListener.class);
- if (listenerMap != null) {
- for (Object target : listenerMap.values()) {
- Method[] methods = target.getClass().getDeclaredMethods();
- if (methods != null && methods.length > 0) {
- for (Method method : methods) {
- ListenPoint l = AnnotatedElementUtils.findMergedAnnotation(method,ListenPoint.class);
- if (l != null) {
- annoListeners.add(new ListenerPoint(target, method, l));
- }
+ if(listenerMap==null){
+ return;
+ }
+ for (Object target : listenerMap.values()) {
+ Method[] methods = target.getClass().getDeclaredMethods();
+ if (methods != null && methods.length > 0) {
+ for (Method method : methods) {
+ ListenPoint l = AnnotatedElementUtils.findMergedAnnotation(method,ListenPoint.class);
+ if (l != null) {
+ annoListeners.add(new ListenerPoint(target, method, l));
}
}
}
}
- log.info("{}: initializing the listeners end.", Thread.currentThread().getName());
- if (log.isWarnEnabled() && listeners.isEmpty() && annoListeners.isEmpty()) {
- log.warn("{}: No listener found in context! ", Thread.currentThread().getName());
+ }
+
+ /**
+ * 初始解析器事件处理器
+ */
+ private void initResolverList(){
+ List list = BeanUtil.getBeansOfType(ResolverCanalEvent.class);
+ if(list==null || list.size()<=0){
+ return;
+ }
+
+ MethodArgumentResolver resolver = MethodArgumentConfig.LISTENERMETHODARGUMENTRESOLVER;
+
+ for (ResolverCanalEvent event : list) {
+ TableFilter filter = event.getClass().getAnnotation(TableFilter.class);
+ if(filter!=null && StringUtils.isNotBlank(filter.schame()) && StringUtils.isNotBlank(filter.table())){
+ String key = filter.schame()+":"+filter.table();
+ List> filterList = MapUtils.getObject(resolverCanalEvents,key,new ArrayList<>());
+ filterList.add(event);
+ resolverCanalEvents.put(key,filterList);
+ resolver.getArgumentClass(event);
+ continue;
+ }
}
}
@Override
protected void process(CanalConnector connector, Map.Entry config) {
- HandlerConf handlerConf = new HandlerConf(listeners,tableCanalEventMap,annoListeners);
+ HandlerConf handlerConf = new HandlerConf(listeners,tableCanalEventMap,annoListeners,resolverCanalEvents);
executor.submit(factory.newTransponder(connector, config,handlerConf));
}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/ResolverCanalEvent.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/ResolverCanalEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7f11a08721f356fdcdfdc1795aff3692dbdbf9f
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/ResolverCanalEvent.java
@@ -0,0 +1,62 @@
+package com.schbrain.canal.client.event;
+
+import com.alibaba.otter.canal.protocol.CanalEntry;
+import com.schbrain.canal.client.conf.MethodArgumentConfig;
+import com.schbrain.canal.client.core.EditMetaInfo;
+import com.schbrain.canal.client.core.MethodArgumentResolver;
+import com.schbrain.canal.client.exception.ReflectionException;
+import com.schbrain.canal.client.utils.Dml;
+import com.schbrain.canal.client.utils.MessageUtil;
+import java.lang.reflect.InvocationTargetException;
+import java.text.ParseException;
+import java.util.List;
+
+public interface ResolverCanalEvent {
+
+
+ default void onEvent(CanalEntry.Entry entry) throws InvocationTargetException, IllegalAccessException, ParseException, ReflectionException {
+ CanalEntry.Header header = entry.getHeader();
+ Dml dml = MessageUtil.parse4Dml(entry);
+ MethodArgumentResolver resolver = MethodArgumentConfig.LISTENERMETHODARGUMENTRESOLVER;
+ List metaInfos = resolver.resolver(this,dml);
+ CanalEntry.EventType eventType = header.getEventType();
+ switch (eventType) {
+ case INSERT:
+ for (EditMetaInfo metaInfo : metaInfos) {
+ onInsert(header, (T) metaInfo.getAfter());
+ }
+ break;
+ case UPDATE:
+ for (EditMetaInfo metaInfo : metaInfos) {
+ onUpdate(header,(T) metaInfo.getBefore(),(T) metaInfo.getAfter());
+ }
+ break;
+ case DELETE:
+ for (EditMetaInfo metaInfo : metaInfos) {
+ onDelete(header,(T) metaInfo.getAfter());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * onInsert
+ * @param t
+ */
+ void onInsert(CanalEntry.Header header, T t);
+
+ /**
+ * onUpdate
+ * @param before
+ * @param after
+ */
+ void onUpdate(CanalEntry.Header header, T before,T after);
+
+ /**
+ * onDelete
+ * @param t
+ */
+ void onDelete(CanalEntry.Header header, T t);
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/SimpleDefCanalEvent.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/SimpleDefCanalEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5dc4f71700dffb5c6be2511d439bbc90361dbdf
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/SimpleDefCanalEvent.java
@@ -0,0 +1,18 @@
+package com.schbrain.canal.client.event;
+
+import com.alibaba.otter.canal.protocol.CanalEntry;
+
+public class SimpleDefCanalEvent implements DefCanalEvent{
+
+ @Override
+ public void onInsert(CanalEntry.Header header, CanalEntry.RowData rowData) {
+ }
+
+ @Override
+ public void onUpdate(CanalEntry.Header header, CanalEntry.RowData rowData) {
+ }
+
+ @Override
+ public void onDelete(CanalEntry.Header header, CanalEntry.RowData rowData) {
+ }
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/SimpleResolverCanalEvent.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/SimpleResolverCanalEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e561af6fe126daf6335bfaf7f8682dfc41eec49e
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/event/SimpleResolverCanalEvent.java
@@ -0,0 +1,23 @@
+package com.schbrain.canal.client.event;
+
+import com.alibaba.otter.canal.protocol.CanalEntry;
+
+/**
+ * @author zhuyf
+ * @date 2022/6/22
+ */
+public class SimpleResolverCanalEvent implements ResolverCanalEvent{
+
+ @Override
+ public void onInsert(CanalEntry.Header header, T o) {
+ }
+
+ @Override
+ public void onUpdate(CanalEntry.Header header, T before, T after) {
+ }
+
+ @Override
+ public void onDelete(CanalEntry.Header header, T o) {
+ }
+
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/PersistenceException.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/PersistenceException.java
new file mode 100644
index 0000000000000000000000000000000000000000..5b829f46c3047fd5ce8921bbb27465740ba967b9
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/PersistenceException.java
@@ -0,0 +1,20 @@
+package com.schbrain.canal.client.exception;
+
+public class PersistenceException extends CanalClientException {
+ private static final long serialVersionUID = -7537395265357977271L;
+
+ public PersistenceException() {
+ }
+
+ public PersistenceException(String message) {
+ super(message);
+ }
+
+ public PersistenceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public PersistenceException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/ReflectionException.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/ReflectionException.java
new file mode 100644
index 0000000000000000000000000000000000000000..a826534cc546e5e46a94a36cdc2a28a9aa12ec82
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/ReflectionException.java
@@ -0,0 +1,21 @@
+package com.schbrain.canal.client.exception;
+
+
+public class ReflectionException extends Exception {
+ private static final long serialVersionUID = 7642570221267566591L;
+
+ public ReflectionException() {
+ }
+
+ public ReflectionException(String message) {
+ super(message);
+ }
+
+ public ReflectionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ReflectionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/TypeException.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/TypeException.java
new file mode 100644
index 0000000000000000000000000000000000000000..15c96d5a150ba628e1420c09eb661685fd8797cd
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/exception/TypeException.java
@@ -0,0 +1,20 @@
+package com.schbrain.canal.client.exception;
+
+public class TypeException extends PersistenceException {
+ private static final long serialVersionUID = 8614420898975117130L;
+
+ public TypeException() {
+ }
+
+ public TypeException(String message) {
+ super(message);
+ }
+
+ public TypeException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TypeException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/schbrain-canal-client/src/main/java/com/schbrain/canal/client/reflector/DefaultObjectFactory.java b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/reflector/DefaultObjectFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e4fb1fb2d549dd7700bdd9f627157d4b765245e
--- /dev/null
+++ b/schbrain-canal-client/src/main/java/com/schbrain/canal/client/reflector/DefaultObjectFactory.java
@@ -0,0 +1,131 @@
+package com.schbrain.canal.client.reflector;
+
+import com.schbrain.canal.client.exception.ReflectionException;
+import com.schbrain.canal.client.transfer.ObjectFactory;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.util.*;
+
+/**
+ * @author zhuyf
+ * @date 2022/6/22
+ */
+public class DefaultObjectFactory implements ObjectFactory, Serializable {
+ private static final long serialVersionUID = -8855120656740914948L;
+
+ public DefaultObjectFactory() {
+ }
+
+ /**
+ * 创建指定类型的对象 不使用构造函数创建
+ * @param type 类型
+ * @param
+ * @return
+ */
+ @Override
+ public T create(Class type) throws ReflectionException {
+ return (T) this.create(type, (List)null, (List)null);
+ }
+
+ /**
+ * 创建指定类型的对象
+ * @param type 类型
+ * @param constructorArgTypes 构造函数参数类型列表
+ * @param constructorArgs 构造函数参数列表
+ * @param
+ * @return
+ */
+ @Override
+ public T create(Class type, List> constructorArgTypes, List