示例中使用的类 (Classes Used in the Examples)
本节罗列了本章各示例中所使用的实体类。
Inventor
java
package org.spring.samples.spel.inventor;
import java.util.Date;
import java.util.GregorianCalendar;
public class Inventor {
private String name;
private String nationality;
private String[] inventions;
private Date birthdate;
private PlaceOfBirth placeOfBirth;
public Inventor(String name, String nationality) {
GregorianCalendar c= new GregorianCalendar();
this.name = name;
this.nationality = nationality;
this.birthdate = c.getTime();
}
public Inventor(String name, Date birthdate, String nationality) {
this.name = name;
this.nationality = nationality;
this.birthdate = birthdate;
}
public Inventor() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNationality() {
return nationality;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
public Date getBirthdate() {
return birthdate;
}
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
public PlaceOfBirth getPlaceOfBirth() {
return placeOfBirth;
}
public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) {
this.placeOfBirth = placeOfBirth;
}
public void setInventions(String[] inventions) {
this.inventions = inventions;
}
public String[] getInventions() {
return inventions;
}
}kotlin
package org.spring.samples.spel.inventor
import java.util.*
class Inventor(
var name: String,
var nationality: String,
var inventions: Array<String>? = null,
var birthdate: Date = GregorianCalendar().time,
var placeOfBirth: PlaceOfBirth? = null)PlaceOfBirth
java
package org.spring.samples.spel.inventor;
public class PlaceOfBirth {
private String city;
private String country;
public PlaceOfBirth(String city) {
this.city=city;
}
public PlaceOfBirth(String city, String country) {
this(city);
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String s) {
this.city = s;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}kotlin
package org.spring.samples.spel.inventor
class PlaceOfBirth(var city: String, var country: String? = null)Society
java
package org.spring.samples.spel.inventor;
import java.util.*;
public class Society {
private String name;
public static String Advisors = "advisors";
public static String President = "president";
private List<Inventor> members = new ArrayList<>();
private Map officers = new HashMap();
public List getMembers() {
return members;
}
public Map getOfficers() {
return officers;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isMember(String name) {
for (Inventor inventor : members) {
if (inventor.getName().equals(name)) {
return true;
}
}
return false;
}
}kotlin
package org.spring.samples.spel.inventor
import java.util.*
class Society {
val Advisors = "advisors"
val President = "president"
var name: String? = null
val members = ArrayList<Inventor>()
val officers = mapOf<Any, Any>()
fun isMember(name: String): Boolean {
for (inventor in members) {
if (inventor.name == name) {
return true
}
}
return false
}
}补充教学
1. SpEL 是如何访问这些类的属性的?
SpEL 默认使用名为 StandardPropertyAccessor 的解析器。它遵循标准的 JavaBeans 命名规范:
- 当你写
placeOfBirth.city时,SpEL 会尝试调用getPlaceOfBirth(),接着在返回的对象上调用getCity()。 - 如果属性是普通的
public字段,SpEL 也会直接读取。
2. Kotlin 的互操作性细节
在示例中,你可以看到 Kotlin 代码非常简洁。
- 属性映射:Kotlin 的
var name: String会在字节码层面自动生成getName()和setName()。SpEL 在运行时能够无缝识别并调用这些生成的方法。 - 默认参数:Kotlin 的默认参数(如
country: String? = null)极大简化了测试数据的构造,这在 SpEL 相关的单元测试中非常有用。
3. 数据类型映射建议
- 日期处理:示例中使用了
java.util.Date。在现代 Spring (6+) 开发中,建议优先使用java.time包下的LocalDate或LocalDateTime。SpEL 同样完美支持java.time类型。 - 泛型集合:虽然
Society使用了ArrayList<Inventor>,但 SpEL 在运行时由于 Java 的泛型擦除特性,其获取的仍然是Object。SpEL 会根据实际运行时的对象类型动态分发方法调用。
4. 为什么这些类都在 Sample 包下?
在学习 SpEL 时,由于它经常涉及 T() 类型操作符和 new 操作符,显式的包路径(如 org.spring.samples.spel.inventor)对于理解 SpEL 的类型定位机制(Type Locator)至关重要。你需要在测试代码中确保这些类在 Classpath 路径下。