@Value注解底层原理(二)
前面介绍了@Value注解的几种解析方式,下面可以是模拟@Value注解如何解析带有SPEL表达式的例子。
测试类如下:
public static void main(String[] args) throws NoSuchFieldException {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestValue.class);ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();resolver.setBeanFactory(context.getDefaultListableBeanFactory());extracted3(context,resolver,Bean4.class.getDeclaredField("value"));}
解析的方法:
private static void extracted3(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver, Field field) {DependencyDescriptor descriptor = new DependencyDescriptor(field,true);//获取@Value的内容String value = resolver.getSuggestedValue(descriptor).toString();System.out.println(value);//解析${}value = context.getEnvironment().resolvePlaceholders(value);System.out.println(value);//解析#{}Object bean3 = context.getBeanFactory().getBeanExpressionResolver().evaluate(value, new BeanExpressionContext(context.getBeanFactory(), null));//类型转换Object res = context.getBeanFactory().getTypeConverter().convertIfNecessary(bean3, descriptor.getDependencyType());System.out.println(res);}
Bean4
static class Bean4{@Value("#{'hello, '+'${JAVA_HOME}'}")private String value;}
测试结果:
第一步是拿到@Value里面的整体内容,第二步解析里面带有${}的字符,第三步解析#{}里面的内容。下面的方法对SPEL表达式进行解析。
Object bean3 = context.getBeanFactory().getBeanExpressionResolver().evaluate(value, new BeanExpressionContext(context.getBeanFactory(), null));
总结一下,无论是@Value注解还是@Autowired注解,其中用到的一些解析器都是类似的。获取属性上的注解然后根据类型不同进行层层处理。Spring底层提供了丰富的注解解析器。