Spring之FactoryBean

简介

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

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值