Bean实例的创建方式及依赖配置

来源:互联网 发布:手机淘宝红包怎么领取 编辑:程序博客网 时间:2024/06/06 19:02

大多数情况下,BeanFactory直接通过new关键字调用构造器来创建Bean实例,而class属性指定了Bean实例的实现类。因此,<bean.../>元素必须指定Bean实例的class属性,但这并不是实例化Bean的唯一方法(使用实例工厂法创建Bean实例,以及使用子Bean方法创建Bean实例时,都可以不指定class属性)。


创建Bean通常有如下方法:

 > 调用构造器创建Bean实例。

 > 调用静态工厂法创建Bean。

 > 调用实例工厂法创建Bean。


1、使用构造器创建Bean实例是最常见的情况,如果采用设值注入的方式,要求该类提供无参数的构造器。在这种情况下,class元素是必需的(除非采用继承),class属性的值就是Bean实例的实现类。

  执行过程:程序创建ApplicationContext实例 → 调用类的默认构造器创建默认实例 → 根据配置文件注入依赖关系:先实例化依赖Bean,然后将依赖Bean注入 → 返回一个完整的实例。


2、使用静态工厂方法创建Bean实例时,class属性也必须指定,但此时class属性并不是指定Bean实例的实现类,而是静态工厂类。Spring需要知道由哪个静态工厂方法来创建Bean实例。除此之外,还需要使用factory-method属性来指定静态工厂方法名,Spring将调用静态工厂方法(可能包含一组参数),来返回一个Bean实例,一旦获得了指定Bean实例,Spring后面的处理步骤与采用普通方法创建Bean实例则完全一样。

package InstanceCreationMethod;public interface Being {public void testBeing();}

package InstanceCreationMethod;public class Dog implements Being {private String msg;public void setMsg(String msg) {this.msg = msg;}@Overridepublic void testBeing() {System.out.println(msg+"汪汪!");}}

package InstanceCreationMethod;public class Cat implements Being {private String msg;public void setMsg(String msg) {this.msg = msg;}@Overridepublic void testBeing() {System.out.println(msg+"喵喵!");}}

package InstanceCreationMethod;//静态工厂类public class BeingFactory {public static Being getBeing(String arg) {if(arg.equalsIgnoreCase("dog")){return new Dog();}else{return new Cat();}}}

<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"><!-- 静态工厂方法创建Bean --><bean id="dog" class="InstanceCreationMethod.BeingFactory" factory-method="getBeing"><constructor-arg value="dog"/><property name="msg" value="狗儿"/></bean><bean id="cat" class="InstanceCreationMethod.BeingFactory" factory-method="getBeing"><constructor-arg value="cat"/><property name="msg" value="猫儿"/></bean></beans>

package InstanceCreationMethod;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");Being b1 = ctx.getBean("dog",Being.class);b1.testBeing();Being b2 = ctx.getBean("cat",Being.class);b2.testBeing();}}


使用静态工厂方法创建实例时必须提供工厂类,工厂类包含产生实例的静态工厂法方法。

执行过程:Spring先解析配置文件,并根据配置文件制定的信息,通过反射调用静态工厂类的静态工厂方法,将该静态工厂方法的返回值作为Bean实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂类负责创建的。创建了Bean实例后,Spring依然可以管理该Bean实例的依赖关闭,包括为其注入所需的依赖关系、管理其生命周期等。


3、实例工厂方法与静态工厂方法只有一点不同:调用静态工厂方法只需使用工厂类即可,调用实例工厂则必须使用工厂实例。所以配置实例工厂方法与配置静态工厂方法也基本相似,只有一点区别:配置静态工厂方法指定静态工厂类,配置实例工厂方法则指定工厂实例。

  使用实例工厂方法时,配置Bean实例的<bean.../>元素无须class属性,因为Spring容器不再直接实例化该Bean,Spring容器仅仅调用实例工厂的工厂方法,工厂方法负责创建Bean实例。


package InstanceCreationMethod;public interface Person {public String sayHello(String name);public String sayGoodBye(String name);}

package InstanceCreationMethod;public class American implements Person {@Overridepublic String sayHello(String name) {return name+",Hello!";}@Overridepublic String sayGoodBye(String name) {return name+",GoodBye!";}}

package InstanceCreationMethod;public class Chinese implements Person {@Overridepublic String sayHello(String name) {return name+",你好!";}@Overridepublic String sayGoodBye(String name) {return name+",下次再见!";}}

package InstanceCreationMethod;public class PersonFactory {public Person getPerson(String ethnic) {if(ethnic.equalsIgnoreCase("chin")){return new Chinese();}else{return new American();}}}

<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"><!-- 实例工厂方法创建Bean --><bean id="personFactory" class="InstanceCreationMethod.PersonFactory"/><bean id="chinese" factory-bean="personFactory" factory-method="getPerson"><constructor-arg value="chin"/></bean><bean id="american" factory-bean="personFactory" factory-method="getPerson"><constructor-arg value="ame"/></bean></beans>


package InstanceCreationMethod;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");Person p1 = ctx.getBean("chinese",Person.class);System.out.println(p1.sayHello("张三"));System.out.println(p1.sayGoodBye("张三"));Person p2 = ctx.getBean("american",Person.class);System.out.println(p2.sayHello("ZhangSan"));System.out.println(p1.sayGoodBye("ZhangSan"));}}


调用实例工厂方法创建Bean,与调用静态工厂方法创建Bean的用法基本相似。区别如下:

 >> 调用实例工厂方法创建Bean,必须将实例工厂配置成Bean实例。而静态工厂方法创建Bean,则无须配置工厂Bean。

 >> 调用实例工厂方法创建Bean,必须使用 factory-bean 属性确定工厂Bean。而静态工厂方法创建Bean,则使用class 元素确定静态工厂类。

相同之处:

 >> 都需使用 factory-method 属性指定产生Bean实例的工厂方法。

 >> 工厂方法如果需要参数,都使用 <constructor-arg.../> 元素指定参数值。

 >> 其他依赖注入属性,都使用 <property.../> 元素确定参数值。