本文dsl实体类由apt-maven-plugin build生成。
我们以四个实体类School, Clazz, Course, User为例。其中User类包含Course类,以此类推,逐层包含。
首先以QUser类为例来看内部实体对象的构建。只贴出了解读用到的代码。
public class QUser extends EntityPathBase<User> {
private static final PathInits INITS = PathInits.DIRECT2;
public static final QUser user = new QUser("user");
public QUser(String variable) {
this(User.class, forVariable(variable), INITS);
}
public QUser(Class<? extends User> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.course = inits.isInitialized("course") ? new QCourse(forProperty("course"), inits.get("course")) : null;
}
}
我们可以看到,Q类的PathInits为PathInits.DIRECT2。当调用Q类的只有PathMetadata的构造参数时,会调用PathInits.getFor(metadata, INITS)方法。而当我们创建Q类时,只有Pathinits.isInitialized()==false时,内部实体对象才为空。
此时我们来看PathInits.DIRECT2的构造方法。
public class PathInits implements Serializable {
private static final long serialVersionUID = -2173980858324141095L;
public static final PathInits DEFAULT = new PathInits();
public static final PathInits DIRECT = new PathInits("*");
public static final PathInits DIRECT2 = new PathInits("*.*");
private final boolean initAllProps;
private final PathInits defaultValue;
private final Map<String,PathInits> propertyToInits = new HashMap<String,PathInits>();
public PathInits(String... initStrs) {
boolean initAllProps = false;
PathInits defaultValue = DEFAULT;
Map<String, Collection<String>> properties = Maps.newHashMap();
for (String initStr : initStrs) {
if (initStr.equals("*")) {
initAllProps = true;
} else if (initStr.startsWith("*.")) {
initAllProps = true;
defaultValue = new PathInits(initStr.substring(2));
} else {
String key = initStr;
List<String> inits = Collections.emptyList();
if (initStr.contains(".")) {
key = initStr.substring(0, initStr.indexOf('.'));
inits = ImmutableList.of(initStr.substring(key.length() + 1));
}
Collection<String> values = properties.get(key);
if (values == null) {
values = new ArrayList<String>();
properties.put(key, values);
}
values.addAll(inits);
}
}
for (Map.Entry<String, Collection<String>> entry : properties.entrySet()) {
PathInits inits = new PathInits(Iterables.toArray(entry.getValue(), String.class));
propertyToInits.put(entry.getKey(), inits);
}
this.initAllProps = initAllProps;
this.defaultValue = defaultValue;
}
}
构造之后的对象如下:
而当初始化QUser时,其内部的对象course对应的QCourse的PathInits为inits.get("course"),我们来看PathInits.get()方法
public PathInits get(String property) {
if (propertyToInits.containsKey(property)) {
return propertyToInits.get(property);
} else if (initAllProps) {
return defaultValue;
} else {
throw new IllegalArgumentException(property + " is not initialized");
}
}
由于propertyToInits为空,所以返回QUser.inits.defaultVaue,即上图中的PathInits@8473,同样QCourse中的clazz PathInits为@8475,而此时initAllProps == false, propertyToInits为空。此时来看Pathinits.isInitialized()方法
public boolean isInitialized(String property) {
return initAllProps || propertyToInits.containsKey(property);
}
此时可以看到,此方法返回false,所以clazz中的school为null, 所以四层实体类对象为空。