关于 Spring @Value 注解的疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
guxingke
V2EX    Java

关于 Spring @Value 注解的疑问

  •  
  •   guxingke
    guxingke 2019 年 9 月 12 日 4857 次点击
    这是一个创建于 2378 天前的主题,其中的信息可能已经有所发展或是发生改变。

    是否有机制可以输出 @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
    BCy66drFCvk1Ou87
        1
    BCy66drFCvk1Ou87  
       2019 年 9 月 12 日
    如果是使用 Java 元注解(@Target、 @Retention、 @Documented 等)自定义的注解的话可以使用反射机制获得注解表达式和表达式的值。Spring 官方的 @Value 也是由 Java 的 @interface+Java 元注解写的 ,应该也可以。
    hantsy
        2
    hantsy  
       2019 年 9 月 12 日
    一般用 Reflect 读取一下类的属性就出来。不过 Spring 有很多工具类可以简化操作,自己看一下其 o.s.util 包下的 AnnnotationUtils,ClassUtils 等。
    nnnToTnnn
        3
    nnnToTnnn  
       2019 年 9 月 12 日
    看到你这个问题特意去看了一下 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
    nnnToTnnn
        4
    nnnToTnnn  
       2019 年 9 月 12 日
    @nnnToTnnn 你写个继承 InjectionMetadata.InjectedElement 的类,放在 Spring 的 IOC 里面然后 debug 查看一下这几个类型了,这个地方是拦截在调用 @Value,设置值的地方,可以拿到你所谓的表达式
    qwerthhusn
        5
    qwerthhusn  
       2019 年 9 月 12 日
    value 里面的${}其实就是个 SpEL,lz 可以从 SpEL 入手,看文档或者源码,应该能找到地方
    BCy66drFCvk1Ou87
        6
    BCy66drFCvk1Ou87  
       2019 年 9 月 12 日
    给 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
    BCy66drFCvk1Ou87
        7
    BCy66drFCvk1Ou87  
       2019 年 9 月 12 日
    Field 是反射的 Field
    ````
    import java.lang.reflect.Field;
    ````
    isir1234
        8
    isir1234  
       2019 年 9 月 12 日   1
    可以实现 BeanPostProcessor 接口, 然后在 postProcessAfterInitialization 方法里把 bean 带 @Value 的字段值打出来
    guxingke
        9
    guxingke  
    OP
       2019 年 9 月 12 日
    @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.
    guxingke
        10
    guxingke  
    OP
       2019 年 9 月 12 日
    @isir1234 漂亮, 此法可行.
    guxingke
        11
    guxingke  
    OP
       2019 年 9 月 12 日
    @HuasLeung 虽然可行, 但是需要自行遍历 class . 不算是个好办法
    guxingke
        12
    guxingke  
    OP
       2019 年 9 月 12 日
    guxingke
        13
    guxingke  
    OP
       2019 年 9 月 12 日
    @HuasLeung 成本稍高
    nnnToTnnn
        14
    nnnToTnnn  
       2019 年 9 月 12 日   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 了,你不说我都快忘了 。

    应该可以解决你的问题(_)
    nnnToTnnn
        15
    nnnToTnnn  
       2019 年 9 月 12 日
    对了 #8 楼也提到了这个方法 =。=
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     951 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 84ms UTC 20:36 PVG 04:36 LAX 13:36 JFK 16:36
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86