一、静态工厂创建 bean
当我们创建一个复杂对象的时候,可以利用工厂模式来创建 bean 对象。
工厂模式:工厂帮我们创建对象,有一个专门帮我们创建对象的类,这个类就是工厂
静态工厂:工厂本身不用创建,通过静态方法调用:对象 = 工厂类.工厂方法名()
实例工厂:工厂本身需要创建对象
工厂类 工厂对象 = new 工厂类();
工厂对象.getAirPlane("");
有这样一个复杂的类 AirPlane:
public class AirPlane {
private String model; //型号
private String wing; //机翼
private Integer personNum; //载客量
private String captain; //机长
// 省略 getter/setter 构造器
}
为其创建静态工厂:
/**
* 静态工厂
*/
public class AirPlaneStaticFactory {
public static AirPlane getAirPlane(String captain) {
System.out.println("AirPlaneStaticFactory正在造飞机。。。");
AirPlane airPlane = new AirPlane();
airPlane.setModel("太行");
airPlane.setPersonNum(300);
airPlane.setWing("50M");
airPlane.setCaptain(captain);
return airPlane;
}
}
把静态工厂配置在容器中:
<!-- 1、静态工厂(不需要创建工厂本身)
class:指定静态工厂全类名
factory-method="getAirPlane" 指定哪个方法是工厂方法
constructor-arg 可以为方法传参
-->
<bean id="airPlane01" class="com.njf.spring.factory.AirPlaneStaticFactory" factory-method="getAirPlane">
<!--为静态方法指定参数-->
<constructor-arg name="captain" value="刘哲"></constructor-arg>
</bean>
测试:
@Test
public void test5() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc3.xml");
AirPlane airPlane01 = (AirPlane) ioc.getBean("airPlane01");
System.out.println("airPlane01 = " + airPlane01);
}
虽然在配置文件中配置的静态工厂,但会帮我们调用工厂方法创建对象。
二、实例工厂创建 bean
创建一个飞机的实例工厂:
public class AirPlaneInstatceFactory {
public AirPlane getAirPlane(String captain) {
System.out.println("AirPlaneInstatceFactory正在造飞机。。。");
AirPlane airPlane = new AirPlane();
airPlane.setModel("太行");
airPlane.setPersonNum(300);
airPlane.setWing("50M");
airPlane.setCaptain(captain);
return airPlane;
}
}
在配置文件中进行配置:
<!-- 实例工厂使用 -->
<bean id="airPlaneInstanceFactory" class="com.njf.spring.factory.AirPlaneInstatceFactory"></bean>
<!--
factory-bean:指定当前对象创建使用哪个工厂
1、先配置出实例工厂对象
2、配置我们要创建的 Airplane 使用哪个工厂创建
(1)factory-bean:指定使用哪个工厂实例
(2)factory-method:使用哪个工厂方法
-->
<bean id="airPlane02" class="com.njf.spring.bean.AirPlane" factory-bean="airPlaneInstanceFactory" factory-method="getAirPlane">
<!--为静态方法指定参数-->
<constructor-arg name="captain" value="王鄂峰"></constructor-arg>
</bean>
测试代码:
@Test
public void test6() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc3.xml");
AirPlane airPlane02 = (AirPlane) ioc.getBean("airPlane02");
System.out.println("airPlane02 = " + airPlane02);
}
这样就可以调用实例工厂创建对应的 bean 对象。
三、实现 FactoryBean 的工厂
Spring 中有两种类型的 bean,一种是 普通的 bean,另一种是工程 bean,即 FactoryBean。
工厂 bean 与普通 bean 不同,其返回的对象不是指定类的一个实例,其返回的是该工程 bean 的 getObject 方法所返回的对象
工厂 bean 必须要实现 org.springframework.beans.factory.FactoryBean 接口
创建 FactoryBean 的实现类:
/**
* 实现了 FactoryBean 接口的类都是Spring可以认识的类,Spring会自动的调用工厂方法创建实例
*
* 1、编写一个 FactoryBean 的实现类
* 2、在Spring的配置文件中进行注册
*
*/
public class MyFactoryBeanImpl implements FactoryBean<Book> {
/**
* getObject: 工厂方法,返回创建的对象
* @return
* @throws Exception
*/
@Override
public Book getObject() throws Exception {
Book book = new Book();
book.setBookName("西游记");
book.setAuthor("吴承恩");
return book;
}
/**
* 返回创建的对象的类型
* Spring会调用这个方法来确认创建的对手是什么类型
* @return
*/
@Override
public Class<?> getObjectType() {
return Book.class;
}
/**
* isSingleton:是单例?
* false:不是单例
* true:是单例
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
}
在Spring 的配置文件中进行注册:
<!--
FactoryBean 是Spring规定的一个接口,只要是该接口的实现类,Spring都认为这是一个工厂。
1、IOC 容器启动的时候不会创建实例
2、FactoryBean 获取的时候才创建对象
-->
<bean id="myFactoryBeanImpl" class="com.njf.spring.factory.MyFactoryBeanImpl"></bean>
测试:
@Test
public void test7() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc3.xml");
Object bean = ioc.getBean("myFactoryBeanImpl");
Object bean2 = ioc.getBean("myFactoryBeanImpl");
System.out.println("bean = " + bean);
System.out.println("bean2 = " + bean2);
System.out.println(bean == bean2); //false
}