最近在学习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