Spring学习(三、Bean对象在Spring中的管理)

Spring学习(三、Bean对象在Spring中的管理)

在大型的系统中,对象的生命周期交给程序管理,大型程序的对象生命周期管理就很麻烦。在Spring中,Spring使用了IOC设计思想,将对象的控制权抽出来,交给程序外的容器管理,减少了程序的代码行数,管理起来就简单了很多。下面是关于IOC和DI的简单介绍:

  • IOC 是Inversion Of Control( 控制反转 )的缩写,它是一种设计思想,是指将对象的控制权由程序代码反转给外部容器。
  • DI 是Dependency Injection( 依赖注入 )的缩写,它是控制反转的另一种说法,同时也为控制反转提供了实现方法。依赖注入是指调用类对其他类的依赖关系由容器注入,这就避免了调用类对其他类的过度依赖,降低了类与类之间的耦合。

一、Bean

Bean简单来说就是Spring容器管理的一个基本单位,所有的对象如果要使用Spring容器来管理,都要将该对象映射成Bean。这是我理解的Bean,具体概念可以看官网。

1.Bean的描述

Spring中常用描述Bean的属性如下:

  • class 指定Bean对应类的全路径

  • name 指定Bean对应对象的一个标识

  • scope 指定Bean对象的作用域

  • id id是Bean对象的唯一标识,Spring通常通过 id属性完成对Bean的配置,管理。

  • lazy-init 是否延时加载,默认值为false

  • init-method 对象初始化方法

  • destory- method 对象销毁方法

2.Bean的作用域

当Spring容器创建一个Bean实例时,不仅可以完成Bean的实例化,还可以为该Bean指定作用域。在Spring容器中,Bean的作用域是指Bean实例相对于其他Bean实例的请求可见范围。Spring支持五种作用域:

  • Singleton:单例模式,作用域为singleton的Bean在Spring容器中只会存在一个共享的Bean实例,所有对Bean的请求只要id与Bean的定义相匹配,则只会返回Bea的同一实例。

  • Prototype:每次从容器中调用Bean时,都会产生一个新的Bean实例。

  • Request:一个HTIP请求会产生一个Bean对象,也就是说,每一个HTTP请求都有自己的Bean实例,只在基于Web的SpringApplicatianC ontext中可用。

  • Session:限定一个Bean的作用域为HTTPsession的生命周期,只有基 于Web的SpringApplicationCorntext才能便用

  • global session:限定一个Bean的作用域为全局HTTPsession的生命周期,只有在Web应用中使用Sping时,该作用域才有效

其中,singleton 和prototype 是两种较为常用的作用域,如果不指定Bean的作用域,Spring会默认该Bean的作用域是singleton。

当Bean的作用域是singleton时,Spring容器只为该Bean创建一个实例,并且该实例可以被重复使用。Spring容器管理着Bean的生命周期,可以控制Bean的创建、初始化、销毁。由于创建和销毁Bean实例会带来一定的系统开销,因此,singleton作用域的Bean避免了反复创建和销毁实例造成的资源消耗。

当Bean的作用域是prototype时,每次调用Bean时Spring容器都会返回一个新的不同的实例,此时,Spring容器只负责创建Bean实例而不再跟踪其生命周期。

3.Bean的生命周期

  • Bean的生命周期是指Bean实例被创建、初始化和销毁的过程。Spring容器可以管理作用域为singleton的Bean的生命周期。对于作用域为prototype的Bean,Spring容器只负责创建实例而不负责跟踪其生命周期。

  • 在Bean的生命周期中,有两个时间节点尤为重要,这两个时间节点分别是Bean实例初始化以后和Bean实例销毁之前,实际开发中,有时需要在这两个时间节点完成一些指定操作,例如,在Bean实例初始化之后申请某些资源、在Bean实例销毁之前回收某些资源等。

  • 为了便于监控Bean生命周期中的特殊节点,Spring提供了相关的API。

    当需要在Bean实例初始化后执行指定行为时,可以通过使用init-method属性或实现initializingBean接口的方式。

    当需要在Bean实例销毁前执行指定行为时,可以通过使用destroy-method属性或实现DisposableBean接口的方式。

二、依赖注入的方式

依赖注入有三种方式,他们分别是构造器注入(对应类的构造函数)、属性注入(对应类的set方法)和接口注入。其中,构造器注入和属性注入是主要方式。

1.构造器注入

student类:

public class Student {
    private String name;
    private String behavior;
    public Student(String name, String behavior) {
        System.out.println("构造器构造Student");
        this.name = name;
        this.behavior = behavior;
    }
    public void init(){
    	System.out.println("Student初始化了,需要申请资源的快点");
    }
    public void destroy(){
    	System.out.println("Student即将销毁了,需要关闭资源的快点");
    }
}

配置文件applicationContext.xml中添加Bean,顺便演示bean的属性用法。

 <!--
        id:唯一标识该类
        class:指定该类的完全限定名
        scope:指定Bean对象的作用域
        lazy-init: sping启动时是否不实例化bean 默认时false
                    当为true时,不实例化bean,只有第一次索要bean时才实例化bean
    -->
 <bean id="student1" class="com.RearlRiver.pojo.Student" scope="singleton" lazy-init="true" init-method="init" destroy-method="destroy">
        <constructor-arg name="name" value="张三" ></constructor-arg>
        <constructor-arg name="behavior" value="学习Java"></constructor-arg>
 </bean>

在bean标签下,通过使用标签,其中name代表类的属性,value代表给属性注入的值,使用构造器注入,类中必须有相应的构造函数。

2.属性注入

student类:

public class Student {
    private String name;
    private String behavior;
    public void setName(String name) {
        this.name = name;
    }
    public void setBehavior(String behavior) {
        this.behavior = behavior;
    }
}

配置文件applicationContext.xml中添加Bean

<bean id="student" class="com.RearlRiver.pojo.Student">
    <property name="name" value="老王"></property>
    <property name="behavior" value="学习Spring"></property>
</bean>

在bean标签下,通过使用标签,其中name代表类的属性,value代表给属性注入的值,使用属性注入,类中必须有相应的setXXX函数。

2.1使用属性注入集合

Gather类:

public class Gather {
    private List<String> myList;
    private Map<String, String> myMap;
    private String[] myArray;
    
    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void setMyArray(String[] myArray) {
        this.myArray = myArray;
    }

    @Override
    public String toString() {
        return "Gather{" +
                "myList=" + myList +
                ", myMap=" + myMap +
                ", myArray=" + Arrays.toString(myArray) +
                '}';
    }
}

配置文件applicationContext.xml中添加Bean

<bean id="gather" class="com.RearlRiver.pojo.Gather">
    <property name="myList">
        <list>
            <value>list0</value>
            <value>list1</value>
            <value>list2</value>
        </list>
    </property>
    <property name="myMap">
        <map>
            <entry key="key0">
                <value>myMap0</value>
            </entry>
            <entry key="key1" value="myMap1">
            </entry>
            <entry key="key2" value="myMap2">
            </entry>
        </map>
    </property>
    <property name="myArray">
        <array>
            <value>myArray0</value>
            <value>myArray1</value>
            <value>myArray2</value>
        </array>
    </property>
</bean>
2.2使用属性注入Spring容器中的其他Bean对象

Student类:

public class Student {
    private String name;
    private String behavior;
    public void setName(String name) {
        this.name = name;
    }
    public void setBehavior(String behavior) {
        this.behavior = behavior;
    }
}

School类:

public class School {
    Student stu;
    public void setStu(Student stu) {
        this.stu = stu;
    }
}

配置文件applicationContext.xml中添加Bean

<bean id="student" class="com.RearlRiver.pojo.Student">
    <property name="name" value="老王"></property>
    <property name="behavior" value="学习Spring"></property>
</bean>
<!--ref的值必须和Student类的bean的id对应-->
<bean id="school" class="com.RearlRiver.pojo.School">
    <!--两种形式-->
    <property name="stu" ref="student"/>
    <property name="tea">
        <ref bean="teacher"></ref>
    </property>
</bean>

三、使用SpEL和 P命名空间注入

通过上面的注入方式,我们要写很多的配置,就很烦。使用SpEL和P命名空间就简洁了很多。当然,没有注解简洁。

<!--使用P:命名空间注入
    注意引入:xmlns:p="http://www.springframework.org/schema/p"
-->
<bean id="student2" class="com.RearlRiver.pojo.Student" p:name="王五" p:behavior="玩游戏"/>
<!--使用SpEL注入
    通过 Bean的 id引用Bean,调用对象的方法或引用对象的属性、计算表达式的值、匹配正则表达式等
-->
<bean id="school1" class="com.RearlRiver.pojo.School">
    <property name="stu" value="#{student}"/>
    <property name="tea" value="#{teacher}"/>
</bean>

四、测试

在之前搭建的环境中,将以上代码更新,在测试类中编写测试函数:

public void springBeansTest(){
    // 通过读取配置文件获取ApplicationContext对象
    ClassPathXmlApplicationContext applicationContext = neClassPathXmlApplicationContext("applicationContext.xml");
    // 通过id值获取Student对象
    Student student1 = applicationContext.getBean("student1", Student.class);
    System.out.println("student1");
    // 关闭容器,此时实例将被销毁
    AbstractApplicationContext ac = (AbstractApplicationContext) applicationContext;
    ac.registerShutdownHook();
}

其他bean的测试类似,只需要通过id拿到,输出看看是否正确。注意:我没重写toString方法,只会打印对象地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值