Spring-6.创建bean的三种方式

时间:2022-11-15 21:20:55

Spring支持使用三种方式创建bean

(1)调用构造器创建bean

(2)静态工厂方法

(3)实例工厂方法

一、构造器创建

给定class属性,bean提供无参构造器(或构造器注入时有参),以反射创建。(之前已有大量例子)

二、静态工厂创建bean(无需创建工厂类实例,工厂方法必须是静态的)

指定以下属性:

(1)class

(2)factory-method

接口:

package codeEETest;
public interface Being
{
public void testBeing();
}
实现类1:

package codeEETest;

public class Dog implements Being
{
private String msg;
// msg的setter方法
public void setMsg(String msg)
{
this.msg = msg;
}
// 实现接口必须实现的testBeing()方法
public void testBeing()
{
System.out.println(msg +
",狗爱啃骨头");
}
}

实现类2:

package codeEETest;

public class Cat implements Being
{
private String msg;
// msg的setter方法
public void setMsg(String msg)
{
this.msg = msg;
}
// 实现接口必须实现的testBeing方法
public void testBeing()
{
System.out.println(msg +
",猫喜欢吃老鼠");
}
}
xml:(以静态工厂方式配置的,一个bean中完成)

<!-- 下面配置驱动Spring调用BeingFactory的静态getBeing()方法来创建Bean
该bean元素包含的constructor-arg元素用于为静态工厂方法指定参数,
因此这段配置会驱动Spring以反射方式来执行如下代码:
dog = org.crazyit.app.factory.BeingFactory.getBeing("dog");
-->

<bean id="dog" class="codeEETest.BeingFactory"
factory-method="getBeing">
<!-- 配置静态工厂方法的参数 -->
<constructor-arg value="dog"/>
<!-- 驱动Spring以"我是狗"为参数来执行dog的setMsg()方法 -->
<property name="msg" value="我是狗"/>
</bean>

<!-- 下面配置会驱动Spring以反射方式来执行如下代码:
dog = org.crazyit.app.factory.BeingFactory.getBeing("cat");
-->

<bean id="cat" class="codeEETest.BeingFactory"
factory-method="getBeing">
<!-- 配置静态工厂方法的参数 -->
<constructor-arg value="cat"/>
<!-- 驱动Spring以"我是猫"为参数来执行dog的setMsg()方法 -->
<property name="msg" value="我是猫"/>
</bean>

测试:

package codeEETest;

import org.springframework.context.*;
import org.springframework.context.support.*;
public class SpringTest
{
public static void main(String[] args)
{
// 以类加载路径下的配置文件创建ClassPathResource实例
ApplicationContext ctx = new ClassPathXmlApplicationContext("codeEETest/beans.xml");
Being b1 = ctx.getBean("dog" , Being.class);
b1.testBeing();
Being b2 = ctx.getBean("cat" , Being.class);
b2.testBeing();
}
//结果:
我是狗,狗爱啃骨头
我是猫,猫喜欢吃老鼠
小结:
核心配置为:(静态工厂,由工厂获得类和注入依赖在一个bean中)
<bean id="dog"  class="codeEETest.BeingFactory"  factory-method="getBeing">

<!-- 配置静态工厂方法的参数 -->

<constructor-arg value="dog"/>

<!-- 驱动Spring以"我是狗"为参数来执行dog的setMsg()方法 -->

<property name="msg" value="我是狗"/>

</bean>

三、实例工厂方法创建bean

实例工厂方法与静态工厂方法只有一点不同:
静态工厂只需使用工厂类即可生产bean,实例工厂方法需要工厂实例。
配置静态工厂方法使用class指定静态工厂类,而配置实例工厂方法则使用factory-bean指定工厂类。
判断静态工厂与实例工厂,看工厂类的方法是不是static即可。

接口:

package codeEETest;
public interface Person
{
// 定义一个打招呼的方法
public String sayHello(String name);
// 定义一个告别的方法
public String sayGoodBye(String name);
}
实现类1:

package codeEETest;
public class Chinese implements Person
{
// 实现Person接口必须实现如下两个方法
public String sayHello(String name)
{
return name + ",您好";
}
public String sayGoodBye(String name)
{
return name + ",下次再见";
}
}
实现类2:

package codeEETest;
public class American implements Person
{
// 实现Person接口必须实现如下两个方法
public String sayHello(String name)
{
return name + ",Hello!";
}
public String sayGoodBye(String name)
{
return name + ",Good Bye!";
}
}
工厂类:

package codeEETest;
public class PersonFactory
{
// 获得Person实例的实例工厂方法
// ethnic参数决定返回哪个Person实现类的实例
public Person getPerson(String ethnic)
{
if (ethnic.equalsIgnoreCase("chin"))
{
return new Chinese();
}
else
{
return new American();
}
}
}
xml:(先由一个bean获得工厂实例,再由一个bean生产所要的对象)

<!-- 配置工厂Bean,该Bean负责产生其他Bean实例 -->
<bean id="personFactory" class="codeEETest.PersonFactory"/>

<!-- 下面配置驱动Spring调用personFactory Bean的getPerson()方法来创建Bean
该bean元素包含的constructor-arg元素用于为工厂方法指定参数,
因此这段配置会驱动Spring以反射方式来执行如下代码:
PersonFactory pf = container.get("personFactory"); // container代表Spring容器
chinese = pf.getPerson("chin"); -->

<bean id="chinese" factory-bean="personFactory" factory-method="getPerson">
<!-- 配置实例工厂方法的参数 -->
<constructor-arg value="chin"/>
</bean>

<!-- 下面配置会驱动Spring以反射方式来执行如下代码:
PersonFactory pf = container.get("personFactory"); // container代表Spring容器
american = pf.getPerson("ame"); -->
<bean id="american" factory-bean="personFactory" factory-method="getPerson">
<constructor-arg value="ame"/>
</bean>
测试:

package codeEETest;


import org.springframework.context.*;
import org.springframework.context.support.*;


public class SpringTest
{
public static void main(String[] args)
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("codeEETest/beans.xml");
Person p1 = ctx.getBean("chinese", Person.class);
System.out.println(p1.sayHello("Mary"));
System.out.println(p1.sayGoodBye("Mary"));
Person p2 = ctx.getBean("american", Person.class);
System.out.println(p2.sayHello("Jack"));
System.out.println(p2.sayGoodBye("Jack"));
}
}
结果:
Mary,您好
Mary,下次再见
Jack,Hello!
Jack,Good Bye!
核心配置:(先得到工厂bean,再获得bean)
<!-- 配置工厂Bean,该Bean负责产生其他Bean实例 -->
<bean id="personFactory" class="codeEETest.PersonFactory"/>


<bean
id="chinese" factory-bean="personFactory"factory-method="getPerson">
<!-- 配置实例工厂方法的参数 -->
<constructor-arg value="chin"/>
</bean>