08Bean的实例化方法

本文详细介绍了Spring框架中四种常见的Bean实例化方法:构造方法、静态工厂模式、工厂方法模式(通过factory-bean)和通过FactoryBean接口实例化,以及它们在配置上的应用和区别。
摘要由CSDN通过智能技术生成

Spring为Bean提供了多种实例化方式,通常包括4种方式。
● 第一种:通过构造方法实例化
● 第二种:通过简单工厂模式实例化
● 第三种:通过factory-bean实例化
● 第四种:通过FactoryBean接口实例化

01通过构造方法实例化

我们之前一直使用的就是这种方式。默认情况下,会调用Bean的无参数构造方法。

package com.sunsplanter.spring6.bean;

public class User {
    public User() {
        System.out.println("User类的无参数构造方法执行。");
    }
}
    <bean id="userBean" class="com.sunsplanter.spring6.bean.User"/>
package com.sunsplanter.spring6.test;

import com.powernode.spring6.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringInstantiationTest {

    @Test
    public void testConstructor(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        User user = applicationContext.getBean("userBean", User.class);
        System.out.println(user);
    }
}

02通过简单工厂模式(静态工厂方法)实例化

第一步:定义一个Bean

package com.sunsplanter.spring6.bean;

public class Vip {
}

第二步:编写简单工厂模式当中的工厂类

package com.sunsplanter.spring6.bean;

public class VipFactory {
//定义一个get方法,返回值是Vip类型的对象
//采用简单工厂模式,一个工厂只对应一个产品,无需"个性化"定制参数,因此定义为为静态方法
    public static Vip get(){
        return new Vip();
    }
}

第三步:在Spring配置文件中指定创建该Bean的方法(使用factory-method属性指定)

<!--既然不是通过默认的无参构造方法获取Bean了,就需要告诉Spring用哪个可以获取Bean
    factory-method方法的参数指定工厂类中的静态方法get,Spring调用该指定的静态方法get创建Bean-->
<bean id="vipBean" class="com.sunsplanter.spring6.bean.VipFactory" factory-method="get"/>

第四步:编写测试程序

@Test
public void testSimpleFactory(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Vip vip = applicationContext.getBean("vipBean", Vip.class);
    System.out.println(vip);
}

03通过工厂方法模式(factory-bean)实例化

这种方式本质上是:通过工厂方法模式进行实例化。
第一步:定义一个Bean

package com.sunsplanter.spring6.bean;

public class Vip {
}

第二步:定义具体工厂类,工厂类中定义实例方法

package com.sunsplanter.spring6.bean;
//采用工厂方法模式,一个工厂对应多个产品,需要根据参数的不同生成对象,因此定义为实例方法
public class VipFactory {
    public Vip get(){
        return new Vip();
    }
}

第三步:在Spring配置文件中指定factory-bean以及factory-method

<!--告诉Spring,调用哪个类(VipFactory)的哪个方法来(get)获取Bean-->
<bean id="vipFactory" class="com.sunsplanter.spring6.bean.VipFactory"/>
<!--可以从后往前看,第二句的factory-bean说明要调用哪个对象(bean),那么当然第一句要先定义个vip的bean(对象)-->
<bean id="vipBean" factory-bean="vipFactory" factory-method="get"/>

第四步:编写测试程序

@Test
public void testSelfFactoryBean(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Vip vipBean = applicationContext.getBean("vipBean", Vip.class);
    System.out.println(vipBean);
}

04通过FactoryBean接口实例化

常用,实际上是对"03通过工厂方法模式(factory-bean)实例化"的简化.


以上的第三种方式中,factory-bean是我们自定义的,factory-method也是我们自己定义的。
在Spring中,当你编写的类直接实现FactoryBean接口之后,factory-bean不需要指定了,factory-method也不需要指定了。
factory-bean会自动指向实现FactoryBean接口的类,factory-method会自动指向getObject()方法。
第一步:定义一个Bean

  package com.sunsplanter.bean;

public class Person {
}

第二步:编写一个类实现FactoryBean接口,必须重写三个方法

package com.sunsplanter.bean;

import org.springframework.beans.factory.FactoryBean;

public class PersonFactoryBean implements FactoryBean<Person> {

    @Override
    public Person getObject() throws Exception {
    //最终这个Bean还是自己new的
        return new Person();
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        // true表示单例
        // false表示原型
        return true;
    }
}

第三步:在Spring配置文件中配置FactoryBean

<bean id="personBean" class="com.sunsplanter.bean.PersonFactoryBean"/>

测试程序:

@Test
public void testFactoryBean(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Person personBean = applicationContext.getBean("personBean", Person.class);
    System.out.println(personBean);
}

05BeanFactory和FactoryBean的区别

BeanFactory:Bean工厂,是Spring IoC容器的顶级类,用来创建bean对象的。

FactoryBean:它是一个Bean,用来辅助Spring创建bean对象。

在Spring中,Bean可以分为两类:
● 第一类:普通Bean
● 第二类:工厂Bean(记住:工厂Bean也是一种Bean,只不过这种Bean比较特殊,它可以辅助Spring实例化其它Bean对象。)


05借助FactoryBean完成Date日期对象的实例化,并用构造方法注入

package com.bean;

import java.util.Date;

public class Student {
    //java.util.Date在Spring被当作简单类型,但若以简单类型注入,其格式要求严格,不够灵活
    //故我们主动将其视为非简单类型,用非简单类型的方法注入
    private Date birth;

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    @Override
    public String toString() {
        return "Student{" +
                "birth=" + birth +
                '}';
    }
}
    <bean id="nowTime" class="java.util.Date"/>

    <bean id="student" class="com.bean.Student">
<!--  将Date视为对象注入,因此用ref而不是Date      -->
        <property name="birth" ref="nowTime"/>
    </bean>

编写测试程序,可正常输出.
但问题是:通过调用Java的Date类,只能输出当前的时间.但既然是注入生日.需求当然是能注入任意时间.

package com.bean;

import java.util.Date;

public class Student {
    //java.util.Date在Spring被当作简单类型,但若以简单类型注入,其格式要求严格,不够灵活
    //故我们主动将其视为非简单类型,用非简单类型的方法注入
    private Date birth;

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    @Override
    public String toString() {
        return "Student{" +
                "birth=" + birth +
                '}';
    }
}
package com.bean;

import org.springframework.beans.factory.FactoryBean;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFactoryBean implements FactoryBean<Date> {

    //流程是传一个yyyy-mm-dd字符串进来,然后用SimpleDateFormat转化成日期对象Date

    //Spring会注入一个日期,那么当然要定义一个变量来接受
    private String date;
    // 通过构造方法给日期字符串属性赋值
    public DateFactoryBean(String date) {
        this.date = date;
    }

    @Override
    public Date getObject() throws Exception {
        //创建一个yyyy--mm--dd的sdf对象,用sdf将yyyy--mm--dd转化成标准日期对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.parse(this.date);
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}
<!--    这是一个工厂Bean,通过其来返回普通Bean:java.util.Date
        只要一获取上下文,自动生成这个Bean,而这个Bean会直接传入一个简单类型的String,通过DateFactoryBean里重写的getObject方法
        String会转成日期对象date,进而将这个date以ref标签通过set的方式注入Student-->
    <bean id="date" class="com.bean.DateFactoryBean">
        <constructor-arg name="date" value="1980-10-11"/>
    </bean>

    <bean id="student" class="com.bean.Student">
    <!--
        property标签的name提示setBirth方法名。
        property标签的ref指定注入的bean对象的id。-->
        <property name="birth" ref="date"/>
    </bean>
@Test
public void testDate(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    Student studentBean = applicationContext.getBean("student", Student.class);
    System.out.println(studentBean);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值