深入理解Spring框架内部:Constants类的关键知识点探索
最编程
2024-07-26 10:31:39
...
最近在学习Spring源码的时候发现有个工具写的蛮不错的,所以分享出来
在AbstractPlatformTransactionManager类中,使用一个String类型的name获取对应常量的值
public final void setTransactionSynchronizationName(String constantName) {
setTransactionSynchronization(constants.asNumber(constantName).intValue());
}
源码学习
Constants是一个常量获取工具,在org.springframework.core包中
This class can be used to parse other classes containing constant definitions
in public static final members. The {@code asXXXX} methods of this class
allow these constant values to be accessed via their string names.
构造函数:通过反射的方式获取目标source类中所有的public static final的常量放入一个Map中
public Constants(Class<?> clazz) {
Assert.notNull(clazz, "Class must not be null");
this.className = clazz.getName();
Field[] fields = clazz.getFields();
for (Field field : fields) {
if (ReflectionUtils.isPublicStaticFinal(field)) {
String name = field.getName();
try {
Object value = field.get(null);
this.fieldCache.put(name, value);
}
catch (IllegalAccessException ex) {
// just leave this field and continue
}
}
}
}
将获取的常量存放在一个Map中
/** The name of the introspected class */
private final String className;
/** Map from String field name to object value */
private final Map<String, Object> fieldCache = new HashMap<>();
常用的几个方法:通过asXX方法取出相应的值
/**
* Return a constant value cast to a Number.
* @param code the name of the field (never {@code null})
* @return the Number value
* @see #asObject
* @throws ConstantException if the field name wasn't found
* or if the type wasn't compatible with Number
*/
public Number asNumber(String code) throws ConstantException {
Object obj = asObject(code);
if (!(obj instanceof Number)) {
throw new ConstantException(this.className, code, "not a Number");
}
return (Number) obj;
}
/**
* Return a constant value as a String.
* @param code the name of the field (never {@code null})
* @return the String value
* Works even if it's not a string (invokes {@code toString()}).
* @see #asObject
* @throws ConstantException if the field name wasn't found
*/
public String asString(String code) throws ConstantException {
return asObject(code).toString();
}
/**
* Parse the given String (upper or lower case accepted) and return
* the appropriate value if it's the name of a constant field in the
* class that we're analysing.
* @param code the name of the field (never {@code null})
* @return the Object value
* @throws ConstantException if there's no such field
*/
public Object asObject(String code) throws ConstantException {
Assert.notNull(code, "Code must not be null");
String codeToUse = code.toUpperCase(Locale.ENGLISH);
Object val = this.fieldCache.get(codeToUse);
if (val == null) {
throw new ConstantException(this.className, codeToUse, "not found");
}
return val;
}
使用demo:
import org.springframework.core.Constants;
/**
* @Author: Kipeng Huang
* @Date: 2018-4-3 15:52
*/
public class ConstantsLearn {
public static final int MAX_NUM = 5;
public static final int MIN_NUM = 2;
public static final String NAME = "kipeng";
public static void main(String[] args) {
Constants constants = new Constants(ConstantsLearn.class);
System.out.println("MAX_NUM:"+constants.asNumber("MAX_NUM").intValue());
System.out.println("NAME:"+constants.asString("NAME"));
}
}
运行结果:
MAX_NUM:5
NAME:kipeng
注意事项:
常量必须是 public static final 修饰的,否则使用asXX方法取出的时候抛exception
public ConstantException(String className, String field, String message) {
super("Field '" + field + "' " + message + " in class [" + className + "]");
}
反射的知识补充
在Constants的构造函数中使用了java反射的部分内容,所以补充下反射的部分知识
- getName 获取类名 包含了包名
- getSimpleName 获取简单的类名 不包含包名
- getFields 获取全部public 的参数
- getDeclaredFields 获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段
- getMethods 获取全部public 的methods
- getDeclaredMethods 获取全部的method including public, protected, default (package) access, and private methods, but excluding inherited methods
下一篇: 简单易学的Java编程在线教程指南