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

关于 Spring @Value 注解的疑问

  •  
  •   guxingke ·
    guxingke · 2019-09-12 10:23:33 +08:00 · 4270 次点击
    这是一个创建于 1932 天前的主题,其中的信息可能已经有所发展或是发生改变。

    是否有机制可以输出 @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-09-12 10:57:05 +08:00
    如果是使用 Java 元注解(@Target、 @Retention、 @Documented 等)自定义的注解的话可以使用反射机制获得注解表达式和表达式的值。Spring 官方的 @Value 也是由 Java 的 @interface+Java 元注解写的 ,应该也可以。
    hantsy
        2
    hantsy  
       2019-09-12 11:09:46 +08:00
    一般用 Reflect 读取一下类的属性就出来。不过 Spring 有很多工具类可以简化操作,自己看一下其 o.s.util 包下的 AnnnotationUtils,ClassUtils 等。
    nnnToTnnn
        3
    nnnToTnnn  
       2019-09-12 11:17:51 +08:00
    看到你这个问题特意去看了一下 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-09-12 11:20:35 +08:00
    @nnnToTnnn 你写个继承 InjectionMetadata.InjectedElement 的类,放在 Spring 的 IOC 里面然后 debug 查看一下这几个类型了,这个地方是拦截在调用 @Value,设置值的地方,可以拿到你所谓的表达式
    qwerthhusn
        5
    qwerthhusn  
       2019-09-12 11:22:43 +08:00
    value 里面的${}其实就是个 SpEL,lz 可以从 SpEL 入手,看文档或者源码,应该能找到地方
    BCy66drFCvk1Ou87
        6
    BCy66drFCvk1Ou87  
       2019-09-12 11:28:32 +08:00
    给 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-09-12 11:29:59 +08:00
    Field 是反射的 Field
    ````
    import java.lang.reflect.Field;
    ````
    isir1234
        8
    isir1234  
       2019-09-12 12:13:58 +08:00   ❤️ 1
    可以实现 BeanPostProcessor 接口, 然后在 postProcessAfterInitialization 方法里把 bean 带 @Value 的字段值打出来
    guxingke
        9
    guxingke  
    OP
       2019-09-12 13:54:17 +08:00
    @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-09-12 13:55:40 +08:00
    @isir1234 漂亮, 此法可行.
    guxingke
        11
    guxingke  
    OP
       2019-09-12 13:56:36 +08:00
    @HuasLeung 虽然可行, 但是需要自行遍历 class . 不算是个好办法
    guxingke
        12
    guxingke  
    OP
       2019-09-12 13:57:12 +08:00
    @hantsy 需要自行遍历, 成本稍高.
    guxingke
        13
    guxingke  
    OP
       2019-09-12 13:57:21 +08:00
    @HuasLeung 成本稍高
    nnnToTnnn
        14
    nnnToTnnn  
       2019-09-12 14:53:09 +08:00   ❤️ 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-09-12 14:54:53 +08:00
    对了 #8 楼也提到了这个方法 =。=
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2990 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 14:33 · PVG 22:33 · LAX 06:33 · JFK 09:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.