Spring 对 bean 的管理细节包括:创建 bean的三种方式、bean 标签的作用范围以及 bean 对象的生命周期,本文针对此部分进行分析与解读。

springboot的默认Bean模式 spring默认管理bean的方式_xml



文章目录

  • 一、创建bean的三种方式
  • 1.1 使用默认构造函数创建
  • 1.2 使用普通工厂中的方法创建对象
  • 1.3 使用工厂中的静态方法创建对象
  • 1.4 工厂模式的注意细节
  • 二、bean 标签的作用范围调整
  • 三、bean 对象的生命周期



一、创建bean的三种方式

工程目录如下:

springboot的默认Bean模式 spring默认管理bean的方式_xml_02

1.1 使用默认构造函数创建

在 spring 的配置文件中使用 bean 标签,配以 id 和 class 属性之后,且没有其他属性和标签时。采用的就是 默认构造函数 创建 bean 对象,此时如果类中没有默认的无参构造函数,则对象 无法创建

<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>

1.2 使用普通工厂中的方法创建对象

这里我们模拟,调用 jar 包中的工厂,并用工厂里的方法来反射创建 bean 对象,并存入spring 容器。
理解:先反射创建工厂对象,然后调用该对象中的 getAccountService 方法得到目标对象,并将其存入容器。

<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>

InstanceFactory.java:

/**
 * 模拟一个工厂类(该类可能是存在与jar包中的,无法通过修改源码的方式提供默认构造函数)
 */
public class InstanceFactory {
    public IAccountService getAccountService(){
        return new AccountServiceImpl();
    }
}

1.3 使用工厂中的静态方法创建对象

使用某个类中的静态方法创建对象,并存入spring容器中

<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>

StaticFactory.java:

/**
 * 模拟一个工厂类(该类可能是存在与jar包中的,无法通过修改源码的方式提供默认构造函数)
 */
public class StaticFactory {
    public static IAccountService getAccountService(){
        return new AccountServiceImpl();
    }
}

1.4 工厂模式的注意细节

工厂模式创建对象有以下两种方式:
方式一:使用反射创建工厂 bean 对象,然后调用方法创建目标对象,并存入 bean 容器。
方式二:使用反射创建工厂 bean 对象,然后调用方法创建对象。
两种方式创建的对象的来源是不同的,方式一来源于 bean 容器,方式二是 new 出来的。以普通工厂举例:

bean.xml:

<?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">

    <!-- 第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)-->
    <bean id="instanceFactory" class="com.axy.factory.InstanceFactory" />
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService" />
</beans>

InstanceFactory.java:

public class InstanceFactory {
    public InstanceFactory() {
        System.out.println("工厂创建了");
    }

    public IAccountService getAccountService(){
        return new AccountServiceImpl();
    }
}

AccountServiceImpl.java:

public class AccountServiceImpl implements IAccountService {
    public AccountServiceImpl(){
        System.out.println("对象创建了");
    }

    public void  saveAccount(){
        System.out.println("service中的saveAccount方法执行了");
    }
}

测试类1:

public class Client {
    public static void main(String[] args) {
        // 1.获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        System.out.println("-----------------");
        // 2.根据id获取Bean对象
        IAccountService as  = (IAccountService)ac.getBean("accountService");
        as.saveAccount();
    }
}

测试结果:

springboot的默认Bean模式 spring默认管理bean的方式_java_03

测试类2:

public class Client {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        System.out.println("-----------------");
        InstanceFactory factory = (InstanceFactory)ac.getBean("instanceFactory");
        IAccountService as = factory.getAccountService();
        as.saveAccount();
    }
}

springboot的默认Bean模式 spring默认管理bean的方式_spring_04


二、bean 标签的作用范围调整

bean标签的scope属性:

  • 作用:用于指定bean的作用范围
  • 取值:常用是单例和多例
  1. singleton : 单例(默认值)
  2. prototype :多例

request :作用域web应用的请求范围
session :作用域web应用的会画范围
global-session :作用域集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session


三、bean 对象的生命周期

  1. 单例对象
    出生:当容器创建时对象出生
    活着:只要容器还在,对象一直在
    死亡:容器销毁,对象消亡
    总结:单例对象的生命周期和容器相同
  2. 多例对象
    出生:当我们使用对象时,spring框架为我们创建
    活着:对象只要是在使用过程中就一直活着
    死亡:当对象长时间不用,或者没有别的对象引用时,由 java 垃圾回收器回收

为了演示 bean 对象的生命周期,我们创建一个工程,工程目录如下:

springboot的默认Bean模式 spring默认管理bean的方式_java_05


注意:factory 包下的类不用看,演示 bean 生命周期涉及不到。

业务层接口及其实现类:

/**
 * 业务层的接口
 */
public interface IAccountService {
    /**
     * 模拟保存账户
     */
    void InsertAccount();
}


/**
 * 业务层实现类
 */
public class AccountServiceImpl implements IAccountService {

    public AccountServiceImpl() {
        System.out.println("对象创建了。。。。");
    }

    public void InsertAccount() {
        System.out.println("service中的InsertAccount方法执行了");
    }

    public void init(){
        System.out.println("对象初始化了。。。。");
    }

    public void destroy(){
        System.out.println("对象销毁了。。。。");
    }
}

bean.xml:

<?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="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="singleton" 
    init-method="init" destroy-method="destroy"></bean>

</beans>

Client.java:

/**
 * 模拟表现层,用于调用业务层
 */
public class Client {
    public static void main(String[] args) {
        //1.获取核心容器对象
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取bean对象
        IAccountService as = (IAccountService) ac.getBean("accountService");
        as.InsertAccount();
        //手动关闭容器
        ac.close();
    }
}

注意: 如果采用 ApplicationContext ac = new ClassPathXmlApplicationContext(“bean.xml”) 的方式获取核心容器,那么容器就没有手动关闭容器 close() 的方法。因为该方法是实现接口,由于 多态,容器对象只能调用父接口的方法,而接口中没有 close() 方法。
但是如果采用该方法来演示多例 bean 对象的生命周期,Spring是不会负责多例对象的销毁,因此不会调用 destory 方法。

测试结果如下:

springboot的默认Bean模式 spring默认管理bean的方式_创建对象_06


本文针对 Spring 对 bean 的管理细节进行分析与讲解,如果大家对文章内容还存在一些疑问,欢迎大家在评论区留言哦~