Spring的核心功能-IOC/DI及基本使用(二)

在上一篇文章Spring的俩大核心功能-IOC/DI(一)讲的是如何将对象交给Spring去管理,下面是如何在配置文件中去配置对象的一些管理。在下面代码中为了简化,我在测试类中提前写好了创建Spring容器的代码。

	ClassPathXmlApplicationContext cpx;

    @Before
    public void init(){
        //测试执行之前执行的方法
        cpx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
    @After
    public void destory(){
        //测试执行之后的方法
        cpx.close();//关闭资源
    }

1.为Bean设置别名

别名就是俩个Bean id引用同一个Bean对象。通过在xml配置文件中使用别名标签实现。

	<bean id="user" class="entity.User"></bean>
    <!--为bean组件设置别名-->
    <alias name="user" alias="aliasUser"/>

获取时就可以通过别名来获取对象。

//根据别名获取对象
User user = cpx.getBean("aliasUser",User.class);

2.Scope属性设置单/多例

  1. 什么是单例?
    在一个系统中,一个类的对象始终是唯一的一个实例,称为单例。
  2. 什么是多例?
    在一个系统中,一个类的对象有多个实例。
  3. Spring默认是按照单例来管理对象。
  4. 设置属性scope=“prototype”后Spring会按照多例来管理对象。
	 <!-- 默认为单例” -->
    <bean id="user" class="entity.User"/>
	<!--设置对象为多例-->
    <bean id="userScope" class="entity.User" scope="prototype"/>

测试,来打印下对象的hashcode比较地址是否相同

 @Test
    public void scopeTest(){
        //多例地址比较
        User user = cpx.getBean("userScope",User.class);
        User user1 = cpx.getBean("userScope",User.class);
        System.out.println(user.hashCode());
        System.out.println(user1.hashCode());

        //单例地址比较
        User user2 = cpx.getBean("user",User.class);
        User user3 = cpx.getBean("user",User.class);
        System.out.println(user2.hashCode());
        System.out.println(user3.hashCode());
    }

运行结果

user:1538399081
user1:1805013491
user2:951880373
user3:951880373

我们可以发现在默认单例的情况下,我们new多个对象他的地址是相同的,设置scope="prototype"后,每次new的对象地址也不相同

3.Spring管理对象生命周期

先说一下一个对象理想的生命周期:

  1. 创建对象
  2. 调用方法执行初始化方法(假设init方法)
  3. 调用对象的方法
  4. 销毁对象之前执行销毁方法,关闭资源(假设destory方法)

当然Spring也提供管理对象生命周期的支持,那么我们如何利用Spring去进行管理。
我们首先创建一个LogWriter对象,在对象中写入三个方法,初始化方法,执行方法,销毁方法。打印测试

package util;

public class LogWriter {

    private void init(){
        System.out.println("开始执行初始化...");
    }

    private void destory(){
        System.out.println("开始销毁对象...");
    }

    public void print(){
        System.out.println("正在执行方法...");
    }
}

在xml配置文件中将这个对象加入管理,Spring提供俩个属性:init-method(初始化方法),destory-method(销毁方法)

<!--完整的生命周期,调用初始化方法与销毁方法-->
<bean id="logWriter" class="util.LogWriter" lazy-init="true" init-method="init" destroy-method="destory"/>

进行测试

 @Test
    public void lifeCycleTest(){
        //Spring管理对象生命周期测试
        LogWriter logWriter = cpx.getBean("logWriter", LogWriter.class);
        logWriter.print();
    }

执行结果

扫描二维码关注公众号,回复: 9782111 查看本文章
开始执行初始化...
正在执行方法...
开始销毁对象...

从结果中可以看到,我们在获取对象,调用print方法之前,Spring帮助我们自动执行了初始化方法,调用print方法之后,自动执行了销毁方法。
注意:当设置对象为多例时,不会自动调用销毁方法,如果必须执行销毁方法,需要我们自己手动调用一下。我们可以测试一下
设置多例

<!--当bean组件为多例时,destory方法不执行-->
<bean id="logWriterScope" class="util.LogWriter" lazy-init="true" init-method="init" destroy-method="destory" scope="prototype"/>

进行测试

 @Test
    public void lifeCycleTest(){
        //多例测试
        LogWriter logWriter1 = cpx.getBean("logWriterScope",LogWriter.class);
        logWriter1.print();
    }

测试结果

开始执行初始化...
正在执行方法...

看打印结果的确不会执行销毁方法。

4.lazy-init属性

在上面代码配置bean组件时,我们方法多了一个lazy-init属性,这个属性叫做懒惰初始化,在使用对象时进行初始化,如果不使用就不初始化,也称为按需初始化。在Spring管理中默认是立即初始化,也就是说你将对象交给Spring进行管理,在Spring容器创建时就将对象进行初始化。在我们设置lazy-init="true"属性后,只有在我们getBean时才进行初始化。可能小伙伴还不明白,我们来测试一下。

我们先测试不加lazy-init属性,采用立即初始化。

<--不加lazy-init属性默认为立即初始化-->
<bean id="logWriter" class="util.LogWriter"  init-method="init" destroy-method="destory"/>

测试方法,什么也不写,但是我们在文章顶部有说明,测试方法执行前自动init方法创建Spring容器

 @Test
    public void lifeCycleTest(){
    }

测试结果

开始执行初始化...
开始销毁对象...

我们发现初始化方法自己执行了。现在我们将lazy-init属性加上

<--测试lazy-init属性-->
<bean id="logWriter" class="util.LogWriter" lazy-init="true" init-method="init" destroy-method="destory"/>

测试方法,我们还是什么都不写

@Test
    public void lifeCycleTest(){
    }

测试结果会发现什么也没有打印。我们在方法中来获取对象在测试一下

@Test
    public void lifeCycleTest(){
        //lazy-init="true"测试
        LogWriter logWriter = cpx.getBean("logWriter", LogWriter.class);
    }

测试结果

开始执行初始化...
开始销毁对象...

结果是我们想的,加上lazy-init属性后,只有我们在获取对象时才进行初始化。
Spring的IOC我们就说完了,基本使用就是这些,大家可以去Spring的官网进行更深入的了解,在下篇文章讲一下DI依赖注入,也是小伙伴有疑问的地方,创建对象执行他的构造方法赋值等。

发布了10 篇原创文章 · 获赞 9 · 访问量 278

猜你喜欢

转载自blog.csdn.net/weixin_45056780/article/details/104730467