Skip to content

Commit 509afe4

Browse files
committed
add FieldProxyFactory
1 parent a647a9e commit 509afe4

File tree

11 files changed

+212
-107
lines changed

11 files changed

+212
-107
lines changed

springboot-starter/pom.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@
6666
<artifactId>spring-boot-starter-web</artifactId>
6767
<scope>test</scope>
6868
</dependency>
69-
<dependency>
70-
<groupId>org.hibernate.orm</groupId>
71-
<artifactId>hibernate-core</artifactId>
72-
</dependency>
7369

7470
</dependencies>
7571

springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/EntityEventInterceptor.java

Lines changed: 0 additions & 35 deletions
This file was deleted.

springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/EntityEventProxy.java

Lines changed: 0 additions & 22 deletions
This file was deleted.

springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/EntityProxyFactory.java

Lines changed: 0 additions & 22 deletions
This file was deleted.

springboot-starter/src/main/java/com/codingapi/springboot/framework/domain/EventProxyEvent.java

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.codingapi.springboot.framework.domain.field;
2+
3+
import com.codingapi.springboot.framework.event.IEvent;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
import lombok.ToString;
7+
8+
/**
9+
* 实体字段变更事件
10+
*/
11+
@Setter
12+
@Getter
13+
@ToString(exclude = {"entity"})
14+
public class FieldChangeEvent implements IEvent {
15+
16+
/**
17+
* 实体对象
18+
*/
19+
private Object entity;
20+
21+
/**
22+
* 实体类名称
23+
*/
24+
private String simpleName;
25+
26+
/**
27+
* 时间戳
28+
*/
29+
private long timestamp;
30+
31+
/**
32+
* 字段名称
33+
*/
34+
private String fieldName;
35+
/**
36+
* 旧的值
37+
*/
38+
private Object oldValue;
39+
/**
40+
* 新的值
41+
*/
42+
private Object newValue;
43+
44+
45+
46+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.codingapi.springboot.framework.domain.field;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
5+
/**
6+
* 实体代理工厂
7+
*/
8+
public class FieldProxyFactory {
9+
10+
public static <T> T create(Class<T> entityClass, Object... args) {
11+
FieldValueInterceptor interceptor = null;
12+
try {
13+
interceptor = new FieldValueInterceptor(entityClass, args);
14+
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
15+
throw new RuntimeException(e);
16+
}
17+
return (T) interceptor.createProxy();
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.codingapi.springboot.framework.domain.field;
2+
3+
import com.codingapi.springboot.framework.event.EventPusher;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.beans.BeanUtils;
6+
import org.springframework.cglib.proxy.Enhancer;
7+
import org.springframework.cglib.proxy.MethodInterceptor;
8+
import org.springframework.cglib.proxy.MethodProxy;
9+
10+
import java.beans.PropertyDescriptor;
11+
import java.lang.reflect.InvocationTargetException;
12+
import java.lang.reflect.Method;
13+
import java.util.HashMap;
14+
import java.util.Map;
15+
16+
/**
17+
* 实体代理
18+
*/
19+
@Slf4j
20+
public class FieldValueInterceptor implements MethodInterceptor {
21+
22+
// 目标类
23+
private final Class<?> targetClass;
24+
// 目标类构造函数参数类型
25+
private final Class<?>[] parameterTypes;
26+
// 目标类构造函数参数
27+
private final Object[] args;
28+
29+
// 目标类实例
30+
private final Object target;
31+
// 目标类属性描述
32+
private final PropertyDescriptor[] propertyDescriptors;
33+
// 目标类属性值
34+
private final Map<String, Object> fields;
35+
36+
public FieldValueInterceptor(Class<?> targetClass, Object... args) throws NoSuchMethodException,
37+
InvocationTargetException, InstantiationException, IllegalAccessException {
38+
this.targetClass = targetClass;
39+
this.args = args;
40+
this.parameterTypes = new Class<?>[args.length];
41+
for (int i = 0; i < args.length; i++) {
42+
parameterTypes[i] = args[i].getClass();
43+
}
44+
this.target = targetClass.getConstructor(parameterTypes).newInstance(args);
45+
this.propertyDescriptors = BeanUtils.getPropertyDescriptors(targetClass);
46+
this.fields = new HashMap<>();
47+
}
48+
49+
50+
/**
51+
* 创建代理
52+
* @return 代理对象
53+
*/
54+
public Object createProxy() {
55+
Enhancer enhancer = new Enhancer();
56+
enhancer.setSuperclass(targetClass);
57+
enhancer.setCallback(this);
58+
return enhancer.create(parameterTypes, args);
59+
}
60+
61+
62+
/**
63+
* 拦截方法
64+
* @param obj 代理对象
65+
* @param method 方法
66+
* @param args 参数
67+
* @param proxy 代理
68+
* @return 方法返回值
69+
* @throws Throwable 异常
70+
*/
71+
@Override
72+
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
73+
// 更新函数肯定有参数,如果没有参数,直接返回
74+
if (method.getParameterCount() <= 0) {
75+
return method.invoke(target, args);
76+
}
77+
78+
if(fields.isEmpty()){
79+
this.readFields();
80+
}
81+
Object result = method.invoke(target, args);
82+
this.compareAndUpdateField();
83+
return result;
84+
}
85+
86+
/**
87+
* 读取Entity字段
88+
* @throws InvocationTargetException InvocationTargetException
89+
* @throws IllegalAccessException InvocationTargetException
90+
*/
91+
private void readFields() throws InvocationTargetException, IllegalAccessException {
92+
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
93+
String name = propertyDescriptor.getName();
94+
Object value = propertyDescriptor.getReadMethod().invoke(target);
95+
fields.put(name, value);
96+
}
97+
}
98+
99+
/**
100+
* 对比字段
101+
* @throws InvocationTargetException InvocationTargetException
102+
* @throws IllegalAccessException InvocationTargetException
103+
*/
104+
private void compareAndUpdateField() throws InvocationTargetException, IllegalAccessException {
105+
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
106+
String name = propertyDescriptor.getName();
107+
Object newValue = propertyDescriptor.getReadMethod().invoke(target);
108+
Object oldValue = fields.get(name);
109+
if (!newValue.equals(oldValue)) {
110+
pushEvent(name, oldValue, newValue);
111+
}
112+
fields.put(name, newValue);
113+
}
114+
}
115+
116+
private void pushEvent(String field, Object oldValue, Object newValue) {
117+
FieldChangeEvent event = new FieldChangeEvent();
118+
event.setEntity(target);
119+
event.setSimpleName(targetClass.getSimpleName());
120+
event.setFieldName(field);
121+
event.setOldValue(oldValue);
122+
event.setNewValue(newValue);
123+
event.setTimestamp(System.currentTimeMillis());
124+
EventPusher.push(event);
125+
}
126+
}

springboot-starter/src/test/java/com/codingapi/springboot/framework/domain/Demo.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55
import com.codingapi.springboot.framework.serializable.JsonSerializable;
66
import com.codingapi.springboot.framework.serializable.MapSerializable;
77
import lombok.Getter;
8-
import lombok.NoArgsConstructor;
9-
import lombok.ToString;
108

11-
@ToString
12-
@NoArgsConstructor
139
public class Demo implements JsonSerializable, MapSerializable {
1410

1511
@Getter
1612
private long id;
13+
1714
@Getter
1815
private String name;
1916

@@ -23,10 +20,10 @@ public Demo(String name) {
2320
}
2421

2522
public void changeName(String name) {
26-
// String beforeName = this.name;
23+
String beforeName = this.name;
2724
this.name = name;
28-
//push event
29-
// EventPusher.push(new DemoChangeEvent(beforeName, name));
25+
// push event
26+
EventPusher.push(new DemoChangeEvent(beforeName, name));
3027
}
3128

3229
}
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package com.codingapi.springboot.framework.domain;
22

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

67
@SpringBootTest
7-
class EntityProxyFactoryTest {
8+
class FieldProxyFactoryTest {
89

910
@Test
1011
void createEntity() {
11-
Demo demo = EntityProxyFactory.createEntity(Demo.class, "test");
12-
System.out.println(demo);
12+
Demo demo = FieldProxyFactory.create(Demo.class, "test");
1313
demo.changeName("123");
1414
}
1515
}

0 commit comments

Comments
 (0)