Skip to content

Commit 6bc635c

Browse files
committed
optimize for deserialize factory class
1 parent a6e7c63 commit 6bc635c

File tree

5 files changed

+101
-15
lines changed

5 files changed

+101
-15
lines changed

core/src/main/java/com/alibaba/fastjson2/reader/FactoryFunction.java

+4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public T apply(Map<Long, Object> values) {
6666
for (int i = 0; i < args.length; i++) {
6767
args[i] = values.get(hashCodes[i]);
6868
}
69+
return createInstance(args);
70+
}
71+
72+
public T createInstance(Object[] args) {
6973
try {
7074
return (T) factoryMethod.invoke(null, args);
7175
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException e) {

core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreator.java

+6-10
Original file line numberDiff line numberDiff line change
@@ -771,18 +771,14 @@ protected <T> ObjectReader<T> createObjectReaderWithCreator(
771771
setterFieldReaders = array;
772772
}
773773

774-
return (ObjectReader<T>) new ObjectReaderNoneDefaultConstructor(
774+
return createNoneDefaultConstructorObjectReader(
775775
objectClass,
776-
beanInfo.typeKey,
777-
beanInfo.typeName,
778-
beanInfo.readerFeatures,
776+
beanInfo,
779777
function,
780778
null,
781779
paramNames,
782780
toFieldReaderArray(fieldReaders),
783-
setterFieldReaders,
784-
beanInfo.seeAlso,
785-
beanInfo.seeAlsoNames
781+
setterFieldReaders
786782
);
787783
}
788784

@@ -1341,7 +1337,7 @@ boolean record = BeanUtils.isRecord(objectClass);
13411337
}
13421338

13431339
protected <T> ObjectReaderNoneDefaultConstructor createNoneDefaultConstructorObjectReader(
1344-
Class<T> objectClass,
1340+
Class objectClass,
13451341
BeanInfo beanInfo,
13461342
Function<Map<Long, Object>, T> constructorFunction,
13471343
List<Constructor> alternateConstructors,
@@ -1359,8 +1355,8 @@ protected <T> ObjectReaderNoneDefaultConstructor createNoneDefaultConstructorObj
13591355
parameterNames,
13601356
paramFieldReaders,
13611357
fieldReaderArray,
1362-
null,
1363-
null
1358+
beanInfo.seeAlso,
1359+
beanInfo.seeAlsoNames
13641360
);
13651361
}
13661362

core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreatorASM.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ public <T> ObjectReader<T> createObjectReader(
340340

341341
@Override
342342
protected <T> ObjectReaderNoneDefaultConstructor createNoneDefaultConstructorObjectReader(
343-
Class<T> objectClass,
343+
Class objectClass,
344344
BeanInfo beanInfo,
345345
Function<Map<Long, Object>, T> constructorFunction,
346346
List<Constructor> alternateConstructors,
@@ -358,18 +358,20 @@ protected <T> ObjectReaderNoneDefaultConstructor createNoneDefaultConstructorObj
358358
parameterNames,
359359
paramFieldReaders,
360360
fieldReaderArray,
361-
null,
362-
null
361+
beanInfo.seeAlso,
362+
beanInfo.seeAlsoNames
363363
);
364364

365365
boolean match = true;
366366

367367
if (beanInfo.autoTypeBeforeHandler != null
368368
|| fieldReaderArray.length != 0
369-
|| !(constructorFunction instanceof ConstructorFunction)
370-
|| !alternateConstructors.isEmpty()
369+
|| (!(constructorFunction instanceof ConstructorFunction) && (!(constructorFunction instanceof FactoryFunction)))
370+
|| (alternateConstructors != null && !alternateConstructors.isEmpty())
371371
|| classLoader.isExternalClass(objectClass)
372372
|| (beanInfo.readerFeatures & JSONReader.Feature.SupportAutoType.mask) != 0
373+
|| (objectReaderAdapter.noneDefaultConstructor != null && objectReaderAdapter.noneDefaultConstructor.getParameterCount() != fieldReaderArray.length)
374+
|| (constructorFunction instanceof FactoryFunction && ((FactoryFunction<T>) constructorFunction).paramNames.length != fieldReaderArray.length)
373375
) {
374376
match = false;
375377
}
@@ -2027,8 +2029,10 @@ private <T> void genMethodReadObject(
20272029
ObjectReaderNoneDefaultConstructor objectReaderNoneDefaultConstructor = (ObjectReaderNoneDefaultConstructor) context.objectReaderAdapter;
20282030
boolean constructDirect = true;
20292031
if (classLoader.isExternalClass(context.objectClass)
2032+
|| context.objectClass.getTypeParameters().length != 0
20302033
|| (objectReaderNoneDefaultConstructor.constructor != null && !Modifier.isPublic(objectReaderNoneDefaultConstructor.constructor.getModifiers()))
20312034
|| (context.objectClass != null && !Modifier.isPublic(context.objectClass.getModifiers()))
2035+
|| objectReaderNoneDefaultConstructor.factoryFunction != null
20322036
) {
20332037
constructDirect = false;
20342038
}

core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderNoneDefaultConstructor.java

+10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public class ObjectReaderNoneDefaultConstructor<T>
2323
final Constructor noneDefaultConstructor;
2424
final BiFunction bifunction;
2525
final Function function;
26+
final FactoryFunction factoryFunction;
2627

2728
public ObjectReaderNoneDefaultConstructor(
2829
Class objectClass,
@@ -66,9 +67,15 @@ public ObjectReaderNoneDefaultConstructor(
6667
if (creator instanceof ConstructorFunction) {
6768
bifunction = ((ConstructorFunction<T>) creator).biFunction;
6869
function = ((ConstructorFunction<T>) creator).function;
70+
factoryFunction = null;
71+
} else if (creator instanceof FactoryFunction) {
72+
bifunction = ((FactoryFunction<T>) creator).biFunction;
73+
function = ((FactoryFunction<T>) creator).function;
74+
factoryFunction = (FactoryFunction) creator;
6975
} else {
7076
bifunction = null;
7177
function = null;
78+
factoryFunction = null;
7279
}
7380
}
7481

@@ -552,6 +559,9 @@ public T createInstance(Object[] args) {
552559
if (bifunction != null) {
553560
return (T) bifunction.apply(args[0], args[1]);
554561
}
562+
if (factoryFunction != null) {
563+
return (T) factoryFunction.createInstance(args);
564+
}
555565
return (T) noneDefaultConstructor.newInstance(args);
556566
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException |
557567
InvocationTargetException e) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.alibaba.fastjson2.read;
2+
3+
import com.alibaba.fastjson2.JSON;
4+
import com.alibaba.fastjson2.annotation.JSONCreator;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
9+
public class FactoryTest {
10+
@Test
11+
public void test1() {
12+
assertEquals(123,
13+
JSON.parseObject("{\"value\": 123}", Bean1.class).value);
14+
}
15+
16+
private static class Bean1 {
17+
private int value;
18+
19+
private Bean1(int value) {
20+
this.value = value;
21+
}
22+
23+
@JSONCreator
24+
public static Bean1 create(int value) {
25+
return new Bean1(value);
26+
}
27+
}
28+
29+
@Test
30+
public void test2() {
31+
assertEquals(123,
32+
JSON.parseObject("{\"id\": 123, \"name\":\"abc\"}", Bean2.class).id);
33+
}
34+
35+
private static class Bean2 {
36+
private int id;
37+
private String name;
38+
39+
public Bean2(int id, String name) {
40+
this.id = id;
41+
this.name = name;
42+
}
43+
44+
@JSONCreator
45+
public static Bean2 create(int id, String name) {
46+
return new Bean2(id, name);
47+
}
48+
}
49+
50+
@Test
51+
public void test3() {
52+
assertEquals(16,
53+
JSON.parseObject("{\"id\": 123, \"name\":\"abc\", \"age\":16}", Bean3.class).age);
54+
}
55+
56+
private static class Bean3 {
57+
private int id;
58+
private String name;
59+
private int age;
60+
61+
public Bean3(int id, String name, int age) {
62+
this.id = id;
63+
this.name = name;
64+
this.age = age;
65+
}
66+
67+
@JSONCreator
68+
public static Bean3 create(int id, String name, int age) {
69+
return new Bean3(id, name, age);
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)