深入Spring专题(22)

149 阅读2分钟

这是我参与2022首次更文挑战的第29天,活动详情查看2022首次更文挑战 从ApplicationContext中检索每个Target bean

public class Target{
	private Foo fooOne;
    private Foo fooTwo;
    private Bar bar;
    
    public Target(){}
    public Target(){
        System.out.println("Target(Foo) called");
    }
    
    public Target(Foo foo,Bar bar){
        System.out.println("Target(Foo,Bar) called");
    }
    public void setFooOne(Foo fooOne){
        this.fooOne=fooOne;
        System.out.println("Poperty fooOne set");
    }
    
    public void setFooTwo(Foo foo){
        this.fooTwo=foo;
        System.out.println("Property fooTwo set");
    }
    
    public void setBar(Bar bar){
        this.bar=bar;
        System.out.println("Property bar set");
    }
    
    public static void main(String... args){
       GenericXmlApplicationContext ctx= new GenericXmlApplicationContext();
        ctx.load("classpath:spring/app-context.xml");
        ctx.refresh();
        
        Target t=null;
        System.out.println("Using byName:\n");
        t=(Target)ctx.getBean("targetByName");
        
        System.out.println("Using byType:\n");
        t=(Target)ctx.getBean("targetByType");
      
        Syste.out.println("Using constructor:\n");
        t=(Target)ctx.getBean("targetConstructor");
        ctx.close();
    }
}

看到Target类有三个构造函数:无参数构造函数、接收Foo实例的构造函数以及接收Foo和Bar实例的构造函数,除了这些构造函数,Target bean还有三个属性,两种Foo类型和一种Bar类型。当调用这些属性和构造函数时,每个属性和构造函数都会向控制台输出写入一条消息。main()方法检索ApplicationContext中声明的每个Target bean,从而触发自动装配过程。输出结果如下:

Using byName:

Property fooOne set

Using byType:

Property bar set
Property fooOne set
Property fooTwo set

Using constructor:
Target(Foo,Bar) called

从输出结果可看,当Spring使用byName模式时,所设置的唯一属性是foo,因为这是配置文件中唯一具有相应bean条目的属性。当使用byType模式时,Spring设置所有三个属性的值,fooOne和fooTwo属性由fooOne bean设置,而bar 属性由barOne bean设置。当使用构造函数时,Spring使用双参数构造函数,因为Spring可为两个参数提供bean,并且不需要回退到另一个构造函数。

​ 当按类型进行自动装配时,如果bean类型相互相关,变得更加复杂,同时,当有多个类实现了相同的接口并且需要自动装配的属性将该接口指定为类型时,就会抛出异常,因为Spring不知道注入哪个bean。