Skip to content
Merged

Dev #24

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<groupId>com.codingapi.springboot</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.1.0</version>
<version>2.1.1</version>

<url>https://github.com/codingapi/springboot-framewrok</url>
<name>springboot-parent</name>
Expand Down
2 changes: 1 addition & 1 deletion springboot-starter-data-fast/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>springboot-parent</artifactId>
<groupId>com.codingapi.springboot</groupId>
<version>2.1.0</version>
<version>2.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion springboot-starter-id-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>springboot-parent</artifactId>
<groupId>com.codingapi.springboot</groupId>
<version>2.1.0</version>
<version>2.1.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion springboot-starter-security-jwt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<artifactId>springboot-parent</artifactId>
<groupId>com.codingapi.springboot</groupId>
<version>2.1.0</version>
<version>2.1.1</version>
</parent>

<artifactId>springboot-starter-security-jwt</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion springboot-starter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.codingapi.springboot</groupId>
<artifactId>springboot-parent</artifactId>
<version>2.1.0</version>
<version>2.1.1</version>
</parent>
<artifactId>springboot-starter</artifactId>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.codingapi.springboot.framework.domain.field;

import com.codingapi.springboot.framework.event.IEvent;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
* 实体字段变更事件
*/
@Setter
@Getter
@ToString(exclude = {"entity"})
public class FieldChangeEvent implements IEvent {

/**
* 实体对象
*/
private Object entity;

/**
* 实体类名称
*/
private String simpleName;

/**
* 时间戳
*/
private long timestamp;

/**
* 字段名称
*/
private String fieldName;
/**
* 旧的值
*/
private Object oldValue;
/**
* 新的值
*/
private Object newValue;



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.codingapi.springboot.framework.domain.field;

import java.lang.reflect.InvocationTargetException;

/**
* 实体代理工厂
*/
public class FieldProxyFactory {

public static <T> T create(Class<T> entityClass, Object... args) {
FieldValueInterceptor interceptor = null;
try {
interceptor = new FieldValueInterceptor(entityClass, args);
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
return (T) interceptor.createProxy();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package com.codingapi.springboot.framework.domain.field;

import com.codingapi.springboot.framework.event.EventPusher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
* 实体代理
*/
@Slf4j
public class FieldValueInterceptor implements MethodInterceptor {

// 目标类
private final Class<?> targetClass;
// 目标类构造函数参数类型
private final Class<?>[] parameterTypes;
// 目标类构造函数参数
private final Object[] args;

// 目标类实例
private final Object target;
// 目标类属性描述
private final PropertyDescriptor[] propertyDescriptors;
// 目标类属性值
private final Map<String, Object> fields;

public FieldValueInterceptor(Class<?> targetClass, Object... args) throws NoSuchMethodException,
InvocationTargetException, InstantiationException, IllegalAccessException {
this.targetClass = targetClass;
this.args = args;
this.parameterTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
parameterTypes[i] = args[i].getClass();
}
this.target = targetClass.getConstructor(parameterTypes).newInstance(args);
this.propertyDescriptors = BeanUtils.getPropertyDescriptors(targetClass);
this.fields = new HashMap<>();
}


/**
* 创建代理
* @return 代理对象
*/
public Object createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(this);
return enhancer.create(parameterTypes, args);
}


/**
* 拦截方法
* @param obj 代理对象
* @param method 方法
* @param args 参数
* @param proxy 代理
* @return 方法返回值
* @throws Throwable 异常
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 更新函数肯定有参数,如果没有参数,直接返回
if (method.getParameterCount() <= 0) {
return method.invoke(target, args);
}

if(fields.isEmpty()){
this.readFields();
}
Object result = method.invoke(target, args);
this.compareAndUpdateField();
return result;
}

/**
* 读取Entity字段
* @throws InvocationTargetException InvocationTargetException
* @throws IllegalAccessException InvocationTargetException
*/
private void readFields() throws InvocationTargetException, IllegalAccessException {
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String name = propertyDescriptor.getName();
Object value = propertyDescriptor.getReadMethod().invoke(target);
fields.put(name, value);
}
}

/**
* 对比字段
* @throws InvocationTargetException InvocationTargetException
* @throws IllegalAccessException InvocationTargetException
*/
private void compareAndUpdateField() throws InvocationTargetException, IllegalAccessException {
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String name = propertyDescriptor.getName();
Object newValue = propertyDescriptor.getReadMethod().invoke(target);
Object oldValue = fields.get(name);
if (!newValue.equals(oldValue)) {
pushEvent(name, oldValue, newValue);
}
fields.put(name, newValue);
}
}

private void pushEvent(String field, Object oldValue, Object newValue) {
FieldChangeEvent event = new FieldChangeEvent();
event.setEntity(target);
event.setSimpleName(targetClass.getSimpleName());
event.setFieldName(field);
event.setOldValue(oldValue);
event.setNewValue(newValue);
event.setTimestamp(System.currentTimeMillis());
EventPusher.push(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class Demo implements JsonSerializable, MapSerializable {

@Getter
private long id;

@Getter
private String name;

Expand All @@ -21,7 +22,7 @@ public Demo(String name) {
public void changeName(String name) {
String beforeName = this.name;
this.name = name;
//push event
// push event
EventPusher.push(new DemoChangeEvent(beforeName, name));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.codingapi.springboot.framework.domain;

import com.codingapi.springboot.framework.domain.field.FieldProxyFactory;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class FieldProxyFactoryTest {

@Test
void createEntity() {
Demo demo = FieldProxyFactory.create(Demo.class, "test");
demo.changeName("123");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.codingapi.springboot.framework.handler;

import com.codingapi.springboot.framework.domain.field.FieldChangeEvent;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Handler
public class EntityFiledChangeHandler implements IHandler<FieldChangeEvent>{

@Override
public void handler(FieldChangeEvent event) {
log.info("field change event -> {}",event);
}
}