首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  Java

关于 Spring @Value 注解的疑问

  •  
  •   guxingke · 3 天前 · 1203 次点击

    是否有机制可以输出 @Value 注解被真实赋值到具体属性上时 , @Value 表达式 和 表达式的值

    e.g

    class Bean {
    
      @Value("${test.val}")
      private String testVal;
      
    }
    
    

    => output

    ${test.val} => hello
    
    15 回复  |  直到 2019-09-12 14:54:53 +08:00
        1
    HuasLeung   3 天前
    如果是使用 Java 元注解(@Target、 @Retention、 @Documented 等)自定义的注解的话可以使用反射机制获得注解表达式和表达式的值。Spring 官方的 @Value 也是由 Java 的 @interface+Java 元注解写的 ,应该也可以。
        2
    hantsy   3 天前
    一般用 Reflect 读取一下类的属性就出来。不过 Spring 有很多工具类可以简化操作,自己看一下其 o.s.util 包下的 AnnnotationUtils,ClassUtils 等。
        3
    nnnToTnnn   3 天前
    看到你这个问题特意去看了一下 Spring @value 这个地方的源码

    这个调用默认的 @value 注解实现逻辑的地方


    https://github.com/spring-projects/spring-framework/blob/48934cba1bc1ae6bc5ef6c03b41ca66d428901ab/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java#L622


    这个地方是注入的地方,或者自己手动继承 InjectionMetadata.InjectedElement 放在 Spring 的 IOC 里面

    这里是扫描注解的地方,依次循环调用继承 InjectionMetadata 的类的,在 Spring IOC 里面

    https://github.com/spring-projects/spring-framework/blob/098ac0bbb88cd178e85b7dc31642bed091560316/spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java#L107

    如有不对的地方希望指出,目前只是看了一下 github 上面的代码,没有 debug 调试,所以理论上是这样


    摸个鱼真难.jpg
        4
    nnnToTnnn   3 天前
    @nnnToTnnn 你写个继承 InjectionMetadata.InjectedElement 的类,放在 Spring 的 IOC 里面然后 debug 查看一下这几个类型了,这个地方是拦截在调用 @Value,设置值的地方,可以拿到你所谓的表达式
        5
    qwerthhusn   3 天前
    value 里面的${}其实就是个 SpEL,lz 可以从 SpEL 入手,看文档或者源码,应该能找到地方
        6
    HuasLeung   3 天前
    给 lz 写了个
    ````
    Class<Bean1> b = Bean1.class;
    Field f = b.getField("testVal");
    if (f.isAnnotationPresent(Value.class)) {
    Value v = f.getAnnotation(Value.class);//获得注解
    System.out.print("@Value 注解的表达式:" + v.value());
    }
    ````
    bean 命名不要写成 Bean
        7
    HuasLeung   3 天前
    Field 是反射的 Field
    ````
    import java.lang.reflect.Field;
    ````
        8
    isir1234   3 天前   ♥ 1
    可以实现 BeanPostProcessor 接口, 然后在 postProcessAfterInitialization 方法里把 bean 带 @Value 的字段值打出来
        9
    guxingke   3 天前
    @nnnToTnnn 感谢回答, 但是继承这个操作不可行, 原因是

    https://github.com/spring-projects/spring-framework/blob/48934cba1bc1ae6bc5ef6c03b41ca66d428901ab/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java#L478

    此处已经制定具体类型 为 AutowiredFieldElement .
    继承之后并不能集成进 spring.
        10
    guxingke   3 天前
    @isir1234 漂亮, 此法可行.
        11
    guxingke   3 天前
    @HuasLeung 虽然可行, 但是需要自行遍历 class . 不算是个好办法
        12
    guxingke   3 天前
    @hantsy 需要自行遍历, 成本稍高.
        13
    guxingke   3 天前
    @HuasLeung 成本稍高
        14
    nnnToTnnn   3 天前   ♥ 1
    @guxingke 不好意思,在 github 上看的稍微有点麻烦,所以看的不仔细。我以为会直接采用 Spring IOC 的容器,没想到 Spring 是直接定制的

    实现一个 BeanPostProcessor 接口放在 IOC 容器里面

    https://github.com/spring-projects/spring-framework/blob/7ac665b18eb6e37fce367a9abe5f23e582abde02/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java#L416

    通过 postProcessBeforeInitialization,可拿到注入的值,以及 @Value 的值。这个可以做到。

    好久没看 spring 了,你不说我都快忘了 。

    应该可以解决你的问题(。・_・)ノ
        15
    nnnToTnnn   3 天前
    对了 #8 楼也提到了这个方法 =。=
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   846 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 19ms · UTC 18:11 · PVG 02:11 · LAX 11:11 · JFK 14:11
    ♥ Do have faith in what you're doing.