简介
Spring中有两种类型的Bean:
第一种:普通Bean,返回的都是Bean本身的对象
第二种:工厂Bean,即FactoryBean,xml中指定的class类型,与返回的是不同的类型。
应用场景:如果普通Bean的配置比较复杂,在配置文件定义时步骤比较多,此时可以使用FactoryBean。
定义FactoryBean
步骤:
1、定义一个类,实现FactoryBean接口
2、将该bean添加到IoC容器中
3、从IoC容器中获取该bean,返回的并是FactoryBean中的getObject()方法返回的对象。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--IoC容器实例化了PreparedStatementFactoryBean,
但最后实际返回的是PreparedStatement。
这就是FactoryBean的作用
-->
<bean id="ps" class="ioc19.PreparedStatementFactoryBean"/>
</beans>
package ioc19;
import org.springframework.beans.factory.FactoryBean;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
/*
*该FactoryBean用来生成PreparedStatement实例
*/
public class PreparedStatementFactoryBean implements FactoryBean<PreparedStatement> {
//生成实例的过程
@Override
public PreparedStatement getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/learn","root","root");
PreparedStatement ps = conn.prepareStatement("select * from t_user");
return ps;
}
//生成实例的过程
@Override
public Class<?> getObjectType() {
//这里之前是return null
//这里返不返回PreparedStatement.class无所谓,因为上边泛型已经制定了类型
//这里还保留这个方法是因为jdk1.5之前没有泛型,就用这个方法来表示生成的实例的类型
//这是为了兼容老版本才保留这个方法的
return PreparedStatement.class;
}
//生成实例是否为单例
@Override
public boolean isSingleton() {
return true;
}
}
package ioc19;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String [] args){
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc19/spring.xml");
System.out.println(ac.getBean("ps"));
}
}
输出结果:直观体会“从IoC容器中获取该bean,返回的并是FactoryBean中的getObject()方法返回的对象”。
月 24, 2020 9:35:27 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@685f4c2e: startup date [Mon Feb 24 09:35:27 CST 2020]; root of context hierarchy
二月 24, 2020 9:35:28 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [ioc19/spring.xml]
com.mysql.jdbc.JDBC4PreparedStatement@25bbe1b6: select * from t_user
FactoryBean与BeanFactory区别
FactoryBean本身是一个工厂,BeanFacotry是一个Bean。
实际操练
通过一个FactoryBean类可以获取不同的bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 练习 -->
<bean id="valentine" class="ioc20.DateFactoryBean">
<property name="year" value="2020"/>
<property name="month" value="2"/>
<property name="day" value="14"/>
<property name="hour" value="12"/>
<property name="minute" value="30"/>
<property name="second" value="00"/>
</bean>
<bean id="double11" class="ioc20.DateFactoryBean">
<property name="year" value="2020"/>
<property name="month" value="11"/>
<property name="day" value="11"/>
<property name="hour" value="00"/>
<property name="minute" value="00"/>
<property name="second" value="00"/>
</bean>
</beans>
package ioc20;
import org.springframework.beans.factory.FactoryBean;
import java.util.Calendar;
import java.util.Date;
/*
*用来生成日期实例的FacotryBean
*/
public class DateFactoryBean implements FactoryBean<Date> {
private int year;
private int month;
private int day;
private int hour;
private int minute;
private int second;
@Override
public Date getObject() throws Exception {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR,year);
//Date中1月是0,为了配置友好,这里处理
calendar.set(Calendar.MONTH,month-1);
calendar.set(Calendar.DAY_OF_MONTH,day);
calendar.set(Calendar.HOUR,hour);
calendar.set(Calendar.MINUTE,minute);
calendar.set(Calendar.SECOND,second);
Date date = calendar.getTime();
return date;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
}
package ioc20;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Date;
public class Test {
public static void main(String [] args){
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc20/spring.xml");
Date valentine = (Date) ac.getBean("valentine");
Date double11 = (Date) ac.getBean("double11");
System.out.println(valentine);
System.out.println(double11);
}
}
测试输出:
Fri Feb 14 12:30:00 CST 2020
Wed Nov 11 00:00:00 CST 2020