一、Spring Bean 作用域

常规的 Spring IoC 容器中Bean的作用域有两种:singleton(单例)和prototype(非单例)

注:基于Web的容器还有其他种作用域,在这就不赘述了。

singleton(单例)

  • singleton是Spring默认的作用域。当 Bean 的作用域为 singleton 时,Spring IoC 容器中只会存在一个共享的 Bean 实例。可以更好地重用对象,节省重复创建对象的开销。
  • 设置方式:将 <bean> 元素的 scope 属性设置为singleton(其实也可以不用设置,因为spring默认就是单例模式)

案例1

1.创建Dept类

public class Dept {
    //部门编号
    private int deptNo;
    //部门名称
    private String deptName;
}

2.编写Spring配置文件,并将scope 属性设置为singleton

<bean id="dept" class="com.bighorn.pojo.Dept" scope="singleton">
</bean>

3.编写运行程序

public static void main(String[] args) {
    //获取IoC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //从容器中获取对象
    Dept dept1 = context.getBean("dept", Dept.class);
    Dept dept2 = context.getBean("dept", Dept.class);
    //打印对象
    System.out.println(dept1);
    System.out.println(dept2);
}

4.结果如下,可以发现打印出的是同一个对象

prototype(原型)

  • prototype表示原型(非单例)模式。当 Bean 的作用域为 prototype时,Spring 容器会在每次请求该 Bean 时,都创建一个新的 Bean 实例。
  • 设置方式:将 <bean> 元素的 scope 属性设置为prototype

案例2

1.只需修改scope 属性为prototype,其他代码不变。

<bean id="dept" class="com.bighorn.pojo.Dept" scope="prototype">
</bean>

2.运行结果如下

小结

spring bean默认为单例,避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高。

像表现层、业务层、数据层、工具类对象只需要调用方法,比较适合交给Spring IoC容器管理

但是像那种需要封装实例的域对象,因为会引发线程安全问题,不适合交给Spring IoC容器管理。

二、Spring Bean生命周期

Spring Bean生命周期:Spring Bean 对象从创建到销毁的整体过程。

Spring Bean生命周期大致可以分为以下 5 个阶段:1.Bean 的实例化、2.Bean 属性赋值、3.Bean 的初始化、4.Bean 的使用、5.Bean 的销毁

Spring 根据 Bean 的作用域来选择 Bean 的管理方式。

  • 对于 singleton 作用域的 Bean ,Spring IoC 容器能够一直追踪bean的生命周期;
  • 对于 prototype 作用域的 Bean ,Spring IoC 容器只负责创建,然后就将 Bean 的实例交给客户端代码管理,Spring IoC 容器将不再跟踪其生命周期。

综上所述: 为了更好研究如何控制bean周期,下面案例中创建的bean默认都使用单例模式。

如何关闭容器

由于ApplicationContext类中没有关闭容器的方法,所以想要关闭容器需要用到ApplicationContext的子类——ClassPathXmlApplicationContext类。该类又有两种方法可以关闭容器

1、close关闭容器

close()方法,在调用的时候关闭容器

//获取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//调用close方法关闭容器
context.close();

2、注册钩子关闭容器

registerShutdownHook()方法,在JVM退出前调用关闭容器

//获取 ClassPathXmlApplicationContext 容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//调用注册狗子关闭容器
context.registerShutdownHook();

生命周期回调

Bean 的生命周期回调方法主要有两种:

  • 初始化回调方法:在 Spring Bean 被初始化后调用,执行一些自定义的回调操作。
  • 销毁回调方法:在 Spring Bean 被销毁前调用,执行一些自定义的回调操作。

我们可以通过以下 2种方式自定义 Bean 的生命周期回调方法:

  • 通过接口实现
  • 通过 XML 配置实现

通过接口设置生命周期

我们可以在 Spring Bean 的 Java 类中,通过实现 InitializingBeanDisposableBean 接口,指定 Bean 的生命周期回调方法。

案例1

1.创建User类,并实现InitializingBean, DisposableBean接口,重写afterPropertiesSet()destroy()方法。代码如下

/**
 * 继承接口,程序初始化回调和销毁回调方法
 */
public class User implements InitializingBean, DisposableBean {
    String name;
    int age;

    //setter方法
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //初始化回调方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("这是初始化回调方法");
    }

    //销毁回调方法
    @Override
    public void destroy() throws Exception {
        System.out.println("这是销毁回调方法");
    }

    //toString方法
    @Override
    public String toString() {
        return "User{"  
            "name='"   name   '\''  
            ", age="   age  
            '}';
    }
}

2.编写spring配置文件

<bean id="user" class="com.bighorn.pojo.User">
    <property name="name" value="bighorn"/>
    <property name="age" value="18"/>
</bean>

3.编写运行程序

public class App {
    public static void main(String[] args) {
        //获取 ClassPathXmlApplicationContext 容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从容器中获取对象
        User user = context.getBean("user", User.class);
        //使用bean
        System.out.println(user);
        //调用close方法关闭容器
        context.close();
    }
}

4.运行结果如下

通过xml设置生命周期

注意:由于通过接口设置生命周期的方式会导致代码的耦合性过高,所以通常情况下,我们会通过xml设置生命周期。

通过 <bean> 元素中的 init-methoddestory-method 属性,指定 Bean 的生命周期回调方法。

案例2

1.创建User类,这次不需要继承那两个接口了,但要在添加两个普通方法(方法名可任意):init()destory()代表初始化和销毁方法。代码如下

/**
 * 通过XML配置指定回调方法
 */
public class User {
    String name;
    int age;

    //setter方法
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //初始化回调方法
    public void init() throws Exception {
        System.out.println("这是初始化回调方法");
    }

    //销毁回调方法
    public void destroy() throws Exception {
        System.out.println("这是销毁回调方法");
    }

    //toString方法
    @Override
    public String toString() {
        return "User{"  
            "name='"   name   '\''  
            ", age="   age  
            '}';
    }
}

2.编写spring配置文件,在<bean>元素里添加init-methoddestroy-method属性,并指定User类中自定义的init和destory方法(关键)

<!--通过XML配置指定回调方法-->
<bean id="user" class="com.bighorn.pojo.User" init-method="init" destroy-method="destroy">
    <property name="name" value="bighorn"/>
    <property name="age" value="18"/>
</bean>

3.运行程序和运行结果都与案例1相同,这里就少些笔墨介绍了

到此这篇关于一文搞懂Spring Bean中的作用域和生命周期的文章就介绍到这了,更多相关Spring Bean作用域 生命周期内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

一文搞懂Spring Bean中的作用域和生命周期的更多相关文章

  1. ios – 不同作用域中相同命名常量的链接器错误

    我有一个名为“ID_KEY”的常量,它在3个单独的.m文件的顶部声明,其中没有包含其他文件.声明如下:而其他两个类也是如此.但是我收到一个链接器错误抱怨同名的多个定义.我的问题是为什么链接器抱怨这个呢?

  2. 15.6 Swift局部引用

    /**局部引用和全局引用1.作用域2.生命周期*/varref:Int=Int.init/**定义一个变量或者常量,如果不是可选类型的话,一定要有初始值。所谓的局部引用就是在代码块里面的引用就是局部引用。作用域生命周期都在该代码块中;离它最近的括号*/iftrue{varref:Student=Student.initref.name="ZHangsan"}//超出作用域啦//ref.name="ZHangsan"

  3. android – 在Jelly Bean平板电脑中隐藏系统栏(生根)

    我有一个AndroidJellyBean平板电脑已经扎根并且试图运行一个应用程序,其中包含隐藏系统栏的代码,但它没有被隐藏,任何人都可以帮助我解决这个问题.获取终端输出:结果包(00000000’….’)虽然我正在获得许可的祝酒:超级用户日志屏幕截图:解决方法当引入ICS时,systemUI类的进程ID从79更改为42.下面的代码适用于您的应用可能正在运行的任何Android版本.

  4. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  5. Spring JdbcTemplate执行数据库操作详解

    JdbcTemplate是Spring框架自带的对JDBC操作的封装,目的是提供统一的模板方法使对数据库的操作更加方便、友好,效率也不错,这篇文章主要介绍了Spring JdbcTemplate执行数据库操作,需要的朋友可以参考下

  6. Spring Batch批处理框架操作指南

    Spring Batch 是 Spring 提供的一个数据处理框架。企业域中的许多应用程序需要批量处理才能在关键任务环境中执行业务操作,这篇文章主要介绍了Spring Batch批处理框架操作指南,需要的朋友可以参考下

  7. Spring详细讲解@Autowired注解

    @Autowired注解可以用在类属性,构造函数,setter方法和函数参数上,该注解可以准确地控制bean在何处如何自动装配的过程。在默认情况下,该注解是类型驱动的注入

  8. 使用Spring AOP实现用户操作日志功能

    这篇文章主要介绍了使用Spring AOP实现了用户操作日志功能,功能实现需要一张记录日志的log表,结合示例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. Spring Security认证器实现过程详解

    一些权限框架一般都包含认证器和决策器,前者处理登陆验证,后者处理访问资源的控制,这篇文章主要介绍了Spring Security认证器实现过程,需要的朋友可以参考下

  10. 一起来了解JavaScript的变量作用域

    这篇文章主要为大家详细介绍了JavaScript变量作用域,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部