Spring中的名称依赖注入在@Bean方法参数中是如何工作的?

6
我了解Spring DI的基本原理。
但我不明白的是,在使用@Bean方法参数注入时,Spring如何知道参数名称以便根据参数名称从其bean工厂中注入bean?
例如,在下面的示例中,方法fernas1fernas2的参数在运行时被擦除。然而,Spring仍然可以将正确的Abbas bean实例注入其中。
@SpringBootApplication
public class DemoApplication {

    @Autowired
    private Abbas abbas1;    // this is understandable, hence the field name is available at runtime

    @Autowired
    private Abbas abbas2;   // this is understandable, hence the field name is available at runtime

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);

        Map<String, Fernas> beansOfType = ctx.getBeansOfType(Fernas.class);
        System.out.println(beansOfType);

        Arrays.stream(DemoApplication.class.getMethods())
                .filter(m -> m.getName().startsWith("fernas"))
                .flatMap(m -> Stream.of(m.getParameters()))
                .map(Parameter::getName)
                .forEach(System.out::println);

        System.out.println(ctx.getBean(DemoApplication.class).abbas1);
        System.out.println(ctx.getBean(DemoApplication.class).abbas2);
    }

    class Abbas {
        String name;

        @Override
        public String toString() {
            return name;
        }
    }

    class Fernas {
        Abbas abbas;

        @Override
        public String toString() {
            return abbas.toString();
        }
    }

    @Bean
    public Abbas abbas1() {
        Abbas abbas = new Abbas();
        abbas.name = "abbas1";
        return abbas;
    }

    @Bean
    public Abbas abbas2() {
        Abbas abbas = new Abbas();
        abbas.name = "abbas2";
        return abbas;
    }

    // this is not understandable, hence the parameter name is NOT available at runtime
    @Bean
    public Fernas fernas1(Abbas abbas1) {
        Fernas fernas1 = new Fernas();
        fernas1.abbas = abbas1;
        return fernas1;
    }

    // this is not understandable, hence the parameter name is NOT available at runtime
    @Bean
    public Fernas fernas2(Abbas abbas2) {
        Fernas fernas2 = new Fernas();
        fernas2.abbas = abbas2;
        return fernas2;
    }
}

编辑: @Javier提供的相同的问题和解决方案都适用于 methodconstructor 参数。

1个回答

4
如果参数名称反射不可用,则使用类文件本身中的信息。请参见DefaultParameterNameDiscoverer
默认实现了ParameterNameDiscoverer策略接口,使用Java 8标准反射机制(如果可用),并回退到基于ASM的LocalVariableTableParameterNameDiscoverer以检查类文件中的调试信息。
例如,DemoApplication.fernas2的LocalVariableTable为:
    Start  Length  Slot  Name   Signature
        0      16     0  this   Lcom/example/demo/DemoApplication;
        0      16     1 abbas2   Lcom/example/demo/DemoApplication$Abbas;
        9       7     2 fernas2   Lcom/example/demo/DemoApplication$Fernas;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接