Spring中的@Scope注解详细讲解及示例

 更新时间:2023年11月24日 09:51:59   作者:扛麻袋的少年  
这篇文章主要介绍了Spring中的@Scope注解详细讲解及示例,@Scope注解是 Spring IOC 容器中的一个作用域,在 Spring IOC 容器中,他用来配置Bean实例的作用域对象,需要的朋友可以参考下

1.@Scope注解是什么

@Scope注解是 Spring IOC 容器中的一个作用域,在 Spring IOC 容器中,他用来配置Bean实例的作用域对象。

@Scope 具有以下几种作用域:

  • singleton 单实例的(单例)(默认)   ----全局有且仅有一个实例
  • prototype 多实例的(多例)   ---- 每次获取Bean的时候会有一个新的实例
  • reqeust    同一次请求 ----request:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
  • session    同一个会话级别 ---- session:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效

注:这边只演示我们常用的 singleton、prototype 两种,其他的可以自己试试

2.@Scope注解怎么使用

直接在bean对象方法上增加@Scope注解即可。

① 在不指定@Scope的情况下,所有的bean都是单实例的bean,而且是饿汉模式加载(容器启动实例就创建好了)

@Bean 
public Person person() { 
	return new Person(); 
}

②指定@Scope为 prototype 表示为多实例的,而且还是懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是 在第一次使用的时候才会创建)

@Bean 
@Scope(value = "prototype") 
public Person person() { 
	return new Person(); 
}

3.singleton/prototype模式演示

/**
 * Person类
 */ 
public class Person {
	// Person类无参构造方法
    public Person() {
        System.out.println("执行Person构造器创建Person对象");
    }
}
/**
 * TODO 主配置类
 *
 * @author : lzb
 * @date: 2021-03-05 13:50
 */
@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = "singleton")
    public Person person(){
        return new Person();
    }
}

3.1 singleton单例演示

@Scope注解默认为singleton单例,singleton实例的意思不管你使用多少次在springIOC容器中只会存在一个实例,演示如下只打印了一次创建实例:

public class DemoApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
        Person person = ac.getBean(Person.class);
        Person person2 = ac.getBean(Person.class);
        System.out.println(person);
        System.out.println(person2);
        System.out.println(person == person2);
    }
}

执行结果:

在这里插入图片描述

可以发现singleton单例模式,在IOC容器中只会有一个实例存在,每次getBean()获取的实例对象都是同一个。

3.2 prototype多例演示

/**
 * TODO 主配置类
 *
 * @author : lzb
 * @date: 2021-03-05 13:50
 */
@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = "prototype")
    public Person person(){
        return new Person();
    }
}

执行结果:

在这里插入图片描述

发现prototype多例模式,每次在调用getBean() 获取实例时,都会重新调用 Person 类的无参构造方法,重新创建一个 Person 对象。

4.恶汉/懒汉

使用singleton单例,采用饿汉加载(容器启动,Bean实例就创建好了)

使用prototype多例,采用懒汉加载(IOC容器启动的时候,并不会创建对象实例,而是在第一次使用的时候才会创建)

4.1 singleton 恶汉

演示

/**
 * TODO 主配置类
 *
 * @author : lzb
 * @date: 2021-03-05 13:50
 */
@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = "singleton")
    public Person person(){
        return new Person();
    }
}
public class DemoApplication {

    public static void main(String[] args) {
    	// 启动Spring IOC容器
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
    }
}

执行结果:

在这里插入图片描述

singleton单例模式,在 IOC 容器启动时,便会去调用 Person 类的无参构造方法,创建一个 Person 对象。此时并没有调用 getBean() 方法来获取Person 对象实例。

所以singleton 采用的是 恶汉式 创建实例对象

注:如何将 singleton 单例模式的 恶汉式 变更为 懒汉式,只需要再添加一个 @Lazy 注解即可。 如下所示:

@Configuration
public class BeanConfig {

    @Bean
    @Scope
    @Lazy
    public Person person(){
        return new Person();
    }
}

4.2 prototype 懒汉

演示

/**
 * TODO 主配置类
 *
 * @author : lzb
 * @date: 2021-03-05 13:50
 */
@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = "prototype")
    public Person person(){
        return new Person();
    }
}
public class DemoApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
        System.out.println("=================IOC容器启动成功==============");
        Person person = ac.getBean(Person.class);
        System.out.println(person);
    }
}

执行结果:

在这里插入图片描述

prototype多例模式,在 IOC 容器启动时,并不会去创建Bean实例,只有在调用 getBean() 方法获取Person 对象时,才会去调用 Person 类的无参构造方法,创建一个 Person 对象。

所以 prototype 采用的是 懒汉式 创建实例对象

5.Bean实例对象的销毁

针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法;

针对多实例bean的话,容器启动的时候,bean是不会被创建的而是在获取bean的时候被创建,而且bean的销毁不受IOC容器的管理,是由GC来处理的

针对每一个Bean实例,都会有一个initMethod() 和 destroyMethod() 方法,我们可以在Bean 类中自行定义,也可以使用 Spring 默认提供的这两个方法。

public class Person {

    public Person() {
        System.out.println("执行Person构造器创建Person对象");
    }

    public void init() {
        System.out.println("initMethod");
    }

    public void destroy() {
        System.out.println("destroyMethod");
    }
}
@Configuration
public class BeanConfig {

    @Bean(initMethod = "init", destroyMethod = "destroy")   // 可以自己指定方法名,也可以不指定,使用Spring默认提供的方法
    @Scope(value = "singleton")
    public Person person(){
        return new Person();
    }
}

singleton单例,在IOC容器销毁时,就会调用 destroyMethod() 方法来将 Bean对象销毁;prototype多例,它的Bean实例对象则不受IOC容器的管理,最终由GC来销毁。

6.@Scope注解的使用场景

几乎90%以上的业务使用 singleton单例就可以,所以 Spring 默认的类型也是singleton,singleton虽然保证了全局是一个实例,对性能有所提高,但是如果实例中有非静态变量时,会导致线程安全问题,共享资源的竞争。

当设置为prototype多例时:每次连接请求,都会生成一个bean实例,也会导致一个问题,当请求数越多,性能会降低,因为创建的实例,导致GC频繁,GC时长增加。

到此这篇关于Spring中的@Scope注解详细讲解及示例的文章就介绍到这了,更多相关Spring中的@Scope注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot实用配置详细图文教程

    springboot实用配置详细图文教程

    SpringBoot从本质上来说就是Spring,它通过了一些自己的特性帮助我们简化了Spring应用程序的开发,下面这篇文章主要给大家介绍了关于springboot实用配置的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • Java中自旋锁与CAS机制的深层关系与区别

    Java中自旋锁与CAS机制的深层关系与区别

    CAS算法即比较并替换,是一种实现并发编程时常用到的算法,Java并发包中的很多类都使用了CAS算法,这篇文章主要介绍了Java中自旋锁与CAS机制深层关系与区别的相关资料,需要的朋友可以参考下
    2025-11-11
  • Java实现树形菜单的方法总结

    Java实现树形菜单的方法总结

    当我们想要展示层级结构,如文件目录、组织结构或分类目录时,树形菜单是一个直观且有效的解决方案,本文为大家整理了java中几种常见方法,希望对大家有所帮助
    2023-08-08
  • java多线程Synchronized实现可见性原理解析

    java多线程Synchronized实现可见性原理解析

    这篇文章主要介绍了java多线程Synchronized实现可见性原理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • spring是如何实现声明式事务的

    spring是如何实现声明式事务的

    这篇文章主要介绍了spring是如何实现声明式事务的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • SpringBoot中@Autowired与@Resource的区别小结

    SpringBoot中@Autowired与@Resource的区别小结

    本文主要介绍了SpringBoot中@Autowired与@Resource的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • Spring myBatis数据库连接异常问题及解决

    Spring myBatis数据库连接异常问题及解决

    这篇文章主要介绍了Spring myBatis数据库连接异常问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Java实现二叉树的示例代码(递归&迭代)

    Java实现二叉树的示例代码(递归&迭代)

    二叉树(Binary tree)是树形结构的一个重要类型。本文将利用Java语言实现二叉树,文中的示例代码讲解详细,需要的同学可以参考一下
    2022-03-03
  • Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解

    Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解

    这篇文章主要介绍了Java 常用类解析:java异常机制,异常栈,异常处理方式,异常链,异常丢失详解的相关资料,需要的朋友可以参考下
    2017-03-03
  • Servlet注解之@WebInitParam多个InitParam的使用

    Servlet注解之@WebInitParam多个InitParam的使用

    这篇文章主要介绍了Servlet注解之@WebInitParam多个InitParam的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论