From 6cbba1252dfb87817b15721140cecded86fe3065 Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Thu, 9 Mar 2017 11:32:05 +0800 Subject: [PATCH] --- article_creator.html | 120 +++++++++++++++++++++++++++---------------- convert.html | 1 - 2 files changed, 75 insertions(+), 46 deletions(-) diff --git a/article_creator.html b/article_creator.html index 9dfb93b71..b63deed6d 100644 --- a/article_creator.html +++ b/article_creator.html @@ -31,51 +31,81 @@
Creator是一个接口, 只有一个public T create(Object... params)方法,可变参数既适合空参数的Constructor也适合含参数的Constructor。得利于Java 8的新语法特性可以在接口上加上静态方法,Creator对象可以通过Creator.create(Class clazz)方法创建。构建原理是通过Constructor的参数来动态创建的。
-Constructor<T> constructor0 = null;
-for (Constructor c : clazz.getConstructors()) { //优先找public 的构造函数
-if (c.getParameterCount() == 0) {
- constructor0 = c;
- break;
- }
-}
-if (constructor0 == null) {//其次找非private带ConstructorProperties的构造函数
- for (Constructor c : clazz.getDeclaredConstructors()) {
- if (Modifier.isPrivate(c.getModifiers())) continue;
- if (c.getAnnotation(ConstructorProperties.class) != null) {
- constructor0 = c;
- break;
- }
- }
-}
-if (constructor0 == null) {//再次找非private且带-parameters编译项的构造函数 java 8以上才支持
- for (Constructor c : clazz.getDeclaredConstructors()) {
- if (Modifier.isPrivate(c.getModifiers())) continue;
- Parameter[] params = c.getParameters();
- if (params.length == 0) continue;
- boolean flag = true;
- for (Parameter param : params) {
- try {
- clazz.getDeclaredField(param.getName());
- } catch (Exception e) {
- flag = false;
- break;
- }
- }
- if (flag) {
- constructor0 = c;
- break;
- }
- }
-}
-if (constructor0 == null) {//最后找非private的空构造函数
- for (Constructor c : clazz.getDeclaredConstructors()) {
- if (Modifier.isPrivate(c.getModifiers())) continue;
- if (c.getParameterCount() == 0) {
- constructor0 = c;
- break;
- }
- }
-} Constructor<T> constructor0 = null;
+ SimpleEntry<String, Class>[] constructorParameters0 = null; //构造函数的参数
+
+ if (constructor0 == null) { // 1、查找public的空参数构造函数
+ for (Constructor c : clazz.getConstructors()) {
+ if (c.getParameterCount() == 0) {
+ constructor0 = c;
+ constructorParameters0 = new SimpleEntry[0];
+ break;
+ }
+ }
+ }
+ if (constructor0 == null) { // 2、查找public带ConstructorProperties注解的构造函数
+ for (Constructor c : clazz.getConstructors()) {
+ ConstructorProperties cp = (ConstructorProperties) c.getAnnotation(ConstructorProperties.class);
+ if (cp == null) continue;
+ SimpleEntry<String, Class>[] fields = ConstructorParameters.CreatorInner.getConstructorField(clazz, cp.value());
+ if (fields != null) {
+ constructor0 = c;
+ constructorParameters0 = fields;
+ break;
+ }
+ }
+ }
+ if (constructor0 == null) { // 3、查找public且不带ConstructorProperties注解的构造函数
+ List<Constructor> cs = new ArrayList<>();
+ for (Constructor c : clazz.getConstructors()) {
+ if (c.getAnnotation(ConstructorProperties.class) != null) continue;
+ if (c.getParameterCount() < 1) continue;
+ cs.add(c);
+ }
+ //优先参数最多的构造函数
+ cs.sort((o1, o2) -> o2.getParameterCount() - o1.getParameterCount());
+ for (Constructor c : cs) {
+ SimpleEntry<String, Class>[] fields = ConstructorParameters.CreatorInner.getConstructorField(clazz, Type.getConstructorDescriptor(c));
+ if (fields != null) {
+ constructor0 = c;
+ constructorParameters0 = fields;
+ break;
+ }
+ }
+ }
+ if (constructor0 == null) { // 4、查找非private带ConstructorProperties的构造函数
+ for (Constructor c : clazz.getDeclaredConstructors()) {
+ if (Modifier.isPublic(c.getModifiers()) || Modifier.isPrivate(c.getModifiers())) continue;
+ ConstructorProperties cp = (ConstructorProperties) c.getAnnotation(ConstructorProperties.class);
+ if (cp == null) continue;
+ SimpleEntry<String, Class>[] fields = ConstructorParameters.CreatorInner.getConstructorField(clazz, cp.value());
+ if (fields != null) {
+ constructor0 = c;
+ constructorParameters0 = fields;
+ break;
+ }
+ }
+ }
+ if (constructor0 == null) { // 5、查找非private且不带ConstructorProperties的构造函数
+ List<Constructor> cs = new ArrayList<>();
+ for (Constructor c : clazz.getDeclaredConstructors()) {
+ if (Modifier.isPublic(c.getModifiers()) || Modifier.isPrivate(c.getModifiers())) continue;
+ if (c.getAnnotation(ConstructorProperties.class) != null) continue;
+ if (c.getParameterCount() < 1) continue;
+ cs.add(c);
+ }
+ //优先参数最多的构造函数
+ cs.sort((o1, o2) -> o2.getParameterCount() - o1.getParameterCount());
+ for (Constructor c : cs) {
+ SimpleEntry<String, Class>[] fields = ConstructorParameters.CreatorInner.getConstructorField(clazz, Type.getConstructorDescriptor(c));
+ if (fields != null) {
+ constructor0 = c;
+ constructorParameters0 = fields;
+ break;
+ }
+ }
+ }
+ 从以上代码可以看出,根据优先级选择Constructor,为了减少学习成本,Creator直接重用了java.beans.ConstructorProperties注解,又因ConstructorProperties只能标记在Constructor上,因此定义一个Creator.ConstructorParameters注解,用于标记在Creator的create方法上。
diff --git a/convert.html b/convert.html index c929291fa..d0acdcfbd 100644 --- a/convert.html +++ b/convert.html @@ -276,7 +276,6 @@ } 通常JavaBean类默认有个public空参数的构造函数,因此大部分情况下不要自定义Creator,其实只要不是private的空参数构造函数Convert都能自动支持(其他的框架都仅支持public的构造函数),只有仅含private的构造函数才需要自定义Creator。带参数的构造函数就需要标记@java.beans.ConstructorProperties,常见于Immutable Object。
- [小技巧]: 若使用Java 8编译项的新特性,带上 -parameters 编译项进行编译的类,带参数的构造函数可以省去@ConstructorProperties注解,Convert会自动匹配参数名动态生成Creator。
Convert 支持自定义Decode、Encode。