按名称的依赖注入如何在Spring @Bean方法参数中起作用

时间:2018-02-04 23:20:11

标签: java spring dependency-injection

我理解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 个答案:

答案 0 :(得分: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;