1.使用构造器创建Bean的实例
默认情况下使用无参数的构造方法来实例化Bean
<bean id="bean1" class="cn.itcast.spring3.demo2.Bean1"></bean>
条件:必须要有无参数构造函数,如果自己定义了有参数的构造函数如果忘了定义无参的构造函数,Spring就会报错,因为Spring底层用到的是反射技术,而反射用到的就是无参数构造函数
2.使用静态工厂方法实例化Bean
使用静态工厂方法实例化Bean时,class属性并不是指定Bean实例的实现类,而是静态工厂类。
通俗的说就是通过工厂来产生类的对象,然后我们调用工厂的方法来获取对象,比无参数构造函数多了一个BeanFactory
下面是类的UML图
Bean是接口,Cat和Dog是实现类,BeanFactory类中通过方法获取Cat和Dog对象
下面是applicationContext.xml配置文件中的内容:
<bean id="dog" class="demo1.BeanFactory" factory-method="getBean">
<!-- 配置静态工厂方法的参数 -->
<constructor-arg value ="dog"/>
<!-- 驱动Spring以我是dog为参数执行dog的setMsg方法 -->
<property name="msg" value="我是dog"/>
</bean>
<bean id="cat" class="demo1.BeanFactory" factory-method="getBean">
<constructor-arg value="cat"/>
<property name="msg" value="我是猫"/>
</bean>
工厂类BeanFactory的代码如下:
public class BeanFactory {
//args参数决定哪个是Bean的实力
public static Bean getBean(String args){
if(args.equalsIgnoreCase("dog")){
return new Dog();
}else{
return new Cat();
}
}
}
下面是测试类的代码和测试结果
@Test
public void test(){
ApplicationContext ctx =
new ClassPathXmlApplicationContext("applicationContext2.xml");
Bean b1 = ctx.getBean("dog",Bean.class);
b1.testBean();
Bean b2 = ctx.getBean("cat",Bean.class);
b2.testBean();
}
测试结果:
Dog的方法 == 我是dog
Cat调用方法==我是猫
总结:
静态工厂方法实例化Bean的方式是:
Spring解析配置文件中的信息,根据配置文件的信息,通过反射调用静态工厂类的静态方法,将静态工厂方法的返回值作为Bean的实例。
而详细的步骤是:
1.Spring加载了XML的配置文件信息
2.通过配置文件中的factory-method="getBean"来指定静态工厂方法创建Bean
3.通过配置文件信息,Spring调用BeanFactory的getBean(String args)方法,并通过配置文件中的`<constructor-arg value ="dog"/>`为方法传入参数,这样就通过静态工厂来创建了一个Bean
4.在测试类中,通过getBean方法获得Bean的子类的实例对象
3.调用实例工厂方法实例化Bean
其实实例化工厂实例化Bean的方法和静态工厂实例化Bean 的区别不大。
静态工厂实例化Bean只需要静态工厂类即可(因为静态工厂类的getBean方法是静态的)
实例化工厂则需要工厂实例。
所以两个方法的配置文件是会不同的。
在上面的基础上,实例工厂的代码是如下:基本没改变只是不再是静态方法了
public class BeanFactory {
//args参数决定哪个是Bean的实力
public Bean getBean(String args){
if(args.equalsIgnoreCase("dog")){
return new Dog();
}else{
return new Cat();
}
}
}
而ApplicationContext.xml的变动就比较大
<bean id="animalFactory" class="demo1.BeanFactory1"/>
<bean id="dog" factory-bean="animalFactory" factory-method="getBean">
<!-- 配置静态工厂方法的参数 -->
<constructor-arg value ="dog"/>
<!-- 驱动Spring以我是dog为参数执行dog的setMsg方法 -->
<property name="msg" value="我是dog"/>
</bean>
<bean id="cat" factory-bean="animalFactory" factory-method="getBean">
<constructor-arg value="cat"/>
<property name="msg" value="我是猫"/>
</bean>
此时的配置文件中改动如下:
<bean../>
元素无需class属性,因为Spring容器不再直接实例化Bean,Spring容器仅仅调用实例工厂的工厂方法
所以第二个变动就是为BeanFactory配置了Bean,负责生产其他的Bean。
还有就是普通的<bean../>
中增加了factory-bean=”animalFactory”这一项
总结:
调用实例方法和静态方法的区别:
1.配置实例工厂方法创建Bean,必须要为实例工厂配置Bean实例,而静态工厂方法则无需配置Bean实例
2.配置静态工厂方法创建Bean,必须以Bean-factory属性确定工厂Bean,而配置静态工厂方法创建Bean,则使用class确定静态工厂类。
相同之处如下:
1.都需要使用factory-method指定产生Bean实例的工厂方法
2.工厂方法如果需要参数则使用<construct-args.../>
元素指定参数值
3.普通的设值注入都是用<property../>
元素确定参数值