【Spring】bean的定义,IoC中bean标签管理对象细节

1. 什么是bean

一般情况用来描述Java中可重用的组件。一个Bean扮演着应用程序素材的角色。JavaBean 是一种JAVA语言写成的可重用组件。

在 Spring 中,构成应用程序主干并由Spring IoC容器管理的对象称为bean。bean是一个由Spring IoC容器实例化、组装和管理的对象。

2. bean标签

被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如在 XML 的表单中的 定义bean标签。

  • 作用:
    用于配置对象让 spring 来创建的。
    默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。

  • 常用属性属性:

    • id: 给对象在容器中提供一个唯一标识。用于获取对象。
    • class: 指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
    • scope: 指定对象的作用范围。
      • singleton :默认值,单例的.
      • prototype :多例的.
      • request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
      • session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
      • global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么globalSession 相当于 session.
    • init-method: 指定类中的初始化方法名称。
    • destroy-method: 指定类中销毁方法名称。

3. bean的作用域

当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton。

Spring 框架支持以下五个作用域,分别为singleton、prototype、request、session和global session,5种作用域说明如下所示,

作用域描述
singleton在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值
prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()
request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境
  • singleton 作用域
    singleton 是默认的作用域,也就是说,当定义 Bean 时,如果没有指定作用域配置项,则 Bean 的作用域被默认为 singleton。

    当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

    也就是说,当将一个bean定义设置为singleton作用域的时候,Spring IoC容器只会创建该bean定义的唯一实例。

    Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。你可以在 bean 的配置文件中设置作用域的属性为 singleton,如下所示:

<bean id="accountService" class="com.siyi.service.impl.AccountServiceImpl" scope="singleton"></bean>
  • prototype 作用域
    当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。

    为了定义 prototype 作用域,你可以在 bean 的配置文件中设置作用域的属性为 prototype,如下所示:

<bean id="accountService" class="com.siyi.service.impl.AccountServiceImpl" scope="prototype"></bean>

4. bean的生命周期

  • 单例对象: scope=“singleton”
    • 一个应用只有一个对象的实例。它的作用范围就是整个引用。
    • 生命周期:
      • 对象出生:当应用加载,创建容器时,对象就被创建了。
      • 对象活着:只要容器在,对象一直活着。
      • 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
  • 多例对象: scope=“prototype”
    • 每次访问对象时,都会重新创建对象实例。
    • 生命周期:
      • 对象出生:当使用对象时,创建新的对象实例。
      • 对象活着:只要对象在使用中,就一直活着。
      • 对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。

理解 Spring bean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。

为了定义安装和拆卸一个 bean,我们只要声明带有 init-methoddestroy-method 参数的 。
init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。
同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。

Bean的生命周期可以表达为:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁

  • 例如:
package com.siyi.service.impl;

import com.siyi.service.IAccountService;

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

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

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

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

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

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.siyi.service.impl.AccountServiceImpl" scope="singleton" init-method="init" destroy-method="destroy"></bean>
</beans>

测试:

package com.siyi.ui;

import com.siyi.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {
    public static void main(String[] args) {
        //1. 获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2. 根据id获取Bean对象
        IAccountService as = (IAccountService)ac.getBean("accountService");
        as.saveAccount();
        //手动关闭容器 注意ApplicationContext是接口
        ((ClassPathXmlApplicationContext) ac).close();
    }
}

运行结果如下:

5. 实例化bean的三种方式

5.1 使用默认无参构造函数

在默认情况下:
它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。

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

5.2 spring 管理静态工厂-使用静态工厂的方法创建对象

/**
* 模拟一个静态工厂,创建业务层实现类
*/
public class StaticFactory {
	public static IAccountService createAccountService(){
		return new AccountServiceImpl();
	}
}
  • 使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
    • id 属性:指定 bean 的 id,用于从容器中获取
    • class 属性:指定静态工厂的全限定类名
    • factory-method 属性:指定生产对象的静态方法
<bean id="accountService" class="com.itheima.factory.StaticFactory" 
	factory-method="createAccountService"></bean>

5.3 spring 管理实例工厂-使用实例工厂的方法创建对象

/**
* 模拟一个实例工厂,创建业务层实现类
* 此工厂创建对象,必须现有工厂实例对象,再调用方法
*/
public class InstanceFactory {
	public IAccountService createAccountService(){
		return new AccountServiceImpl();
	}
}

先把工厂的创建交给 spring 来管理。
然后在使用工厂的 bean 来调用里面的方法

  • factory-bean 属性:用于指定实例工厂 bean 的 id。
  • factory-method 属性:用于指定实例工厂中创建对象的方法。
<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instancFactory"
	factory-method="createAccountService"></bean>
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页