Spring创建实例bean的几种方式(静态工厂,实例工厂...)

本文详细介绍了Spring中创建bean的多种方式,包括构造器实例化、静态工厂和实例工厂方法。强调了静态工厂和实例工厂在配置文件中的区别,以及通过实现FactoryBean接口创建bean的特殊之处。总结了何时选择使用工厂方法创建bean的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用Spring容器创建bean的方式有以下几种:

  1. 容器调用需要实例化的类的构造函数,可以带参,也可以不带参数。
  2. 通过静态工厂模式。
  3. 通过实例工厂模式。

第一种

首先自己创建一个类

package cn.edou.createBean;

/**
 * @author 中森明菜
 * @create 2019-04-20 18:58
 */
public class FirstCreateBean {
    private String name;

    public FirstCreateBean() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

然后在配置文件中声明bean,有一个属性是name,注入value值

  <bean id="firstBean" class="cn.edou.createBean.FirstCreateBean">
        <property name="name" value="创建bean的第一种方式"></property>
    </bean>

测试运行

public class TestGetBean {
    public static void main(String[] args){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        FirstCreateBean firstCreateBean = (FirstCreateBean) ac.getBean("firstBean");
        System.out.println(firstCreateBean.getName());
    }
}

小结:这一种实例化bean的方式是最常见的,它会在上下文加载配置文件的时候,读取配置文件中bean的信息并且实例化。(提示:BeanFactory与ApplicationContext的区别就是前者在调用getBean()的时候才会实例化bean,而后者在容器加载配置文件的时候就会实例化bean,前者属于延迟加载,后者的话缺点是bean非常多的状况下会占用空间,加载慢。

第二种(静态工厂方式创建bean)

首先我们模拟一个人的接口,然后创建实现这个接口的两个实现类,学生和老师;

  • 接口
public interface Person {
    public void zhize();
}
  • 实现类:Student
public class Student implements Person {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void zhize() {
        System.out.println(name+":读书");
    }
}
  • 实现类:Teacher
public class Teacher implements Person {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void zhize() {
        System.out.println(name+":教书");
    }
}
  • 静态工厂
  //静态工厂的静态方法,由它负责bean的实例化
    public static Person getInstance(String type){
        if("student".equals(type)){
            return new Student();
        }else{
            return new Teacher();
        }
    }
  • 配置文件
  	<bean id="teacher" class="cn.edou.createBean.SecondCreateBean" factory-method="getInstance">
        <constructor-arg value="teacher"/>
        <property name="name" value="我是老师"/>
    </bean>
    <bean id="student" class="cn.edou.createBean.SecondCreateBean" factory-method="getInstance">
        <constructor-arg value="student"/>
        <property name="name" value="我是学生"/>
    </bean>
  • 测试
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) ac.getBean("student");
        student.zhize();
        Teacher teacher = (Teacher) ac.getBean("teacher");
        teacher.zhize();
  • 结果
我是学生:读书
我是老师:教书

小结:用静态工厂来实例bean的话需要我们创建一个工厂类,提供一个静态的方法,此方法负责bean的实例化,上面的配置文件的参数详解:

 <constructor-arg value="teacher"/>
 静态工厂方法参数的注入,值是teacher
 然后在调用静态方法的时候会根据值来判断实例化哪个bean
 factory-method="getInstance"
 值为静态方法名

在配置bean的时候,class属性不是实例化bean的全限定类名,而是静态工厂类。

	<bean id="teacher" class="cn.edou.createBean.SecondCreateBean" factory-method="getInstance">
        ...
    </bean>

实例工厂方法创建bean

其实,实例工厂与静态工厂的区别就是前者需要在容器中将工厂实例化,后者不需要实例化工厂,直接调用静态方法即可,因为静态方法可以直接通过类名调用,所以不用将工厂实例化,那么例子也很简单,直接将上面的工厂类的方法中static去除,再改动一下配置文件。

  • 配置文件
	<bean id="factory" class="cn.edou.createBean.ThirdCreateBean"></bean>
    <bean id="fac_teacher" factory-bean="factory" factory-method="getInstance">
        <constructor-arg value="teacher"/>
        <property name="name" value="我是老师"/>
    </bean>
    <bean id="fac_student" factory-bean="factory" factory-method="getInstance">
        <constructor-arg value="student"/>
        <property name="name" value="我是学生"/>
    </bean>
  • 实例工厂类
public class ThirdCreateBean {
    public Person getInstance(String type){
        if("student".equals(type)){
            return new Student();
        }else{
            return new Teacher();
        }
    }
}

测试和结果都与静态工厂一样。

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) ac.getBean("fac_student");
        student.zhize();
        Teacher teacher = (Teacher) ac.getBean("fac_teacher");
        teacher.zhize();
我是学生:读书
我是老师:教书

小结:需要注意的是在配置文件中,bean的factory-bean属性值是工厂id。

 factory-bean="factory" factory-method="getInstance"

彩蛋(通过实现FactoryBean接口来创建一个工厂)

工厂类实现org.springframework.beans.factory.FacotryBean接口,实现了这个接口的类,会添加三个未实现的方法,getObject(),getObjectType(),isSingleton()
实现FactoryBean接口的类不会被视为普通的Bean,Spring会自动检测,调用getObject方法获取Bean实例,而且配置文件中和普通bean的写法一样。

<bean id="factoryBean" class="cn.edou.createBean.FactoryBean"></bean>
  • 工厂类
public class FactoryBean implements org.springframework.beans.factory.FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new Person() {
            @Override
            public void zhize() {
                System.out.println("活着就好");
            }
        };
    }

    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
  • 测试与结果
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = (Person) ac.getBean("factoryBean");
        person.zhize();
活着就好

总结:

什么时候我们会需要用到静态工厂或者实例化工厂来实例化bean?
当我们不希望由容器来负责bean的实例化,而由我们自己来掌控何时实例化bean的时候,我们会用到工厂。
在网上看的的总结也不错,大家可以看看
如何在Spring中不再使用Spring创建Bean实例,而是把Bean创建过程转移到开发者手中。

使用静态工厂方法创建实例时必须提供工厂类和产生实例的静态工厂方法。通过静态工厂方法创建实例时需要对Spring配置文件做如下改变;

  1. class属性不在是Bean实例的实现类,而是生成Bean实例的静态工厂类
  2. 使用factory-method指定生产Bean实例的静态工厂方法
  3. 如果静态工厂方法需要参数,使用元素为其配置

当我们指定Spring使用静态工厂方法来创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,并将该静态工厂方法的返回值作为Bean实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂方法提供的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值