3、spring注解学习(组件注册)——@Scope注解设置组件作用域、@Lazy单例对象懒加载设置

1、spring主配置类注册一个Person组件

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Scope;

import com.atguigu.bean.Person;

//配置类==配置文件
@Configuration        //告诉Spring这是一个配置类
@ComponentScan(value="com.atguigu",        //指定要扫描的包
        excludeFilters= {@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})}  //指定以某种规则排除扫描哪些组件
        /*includeFilters= {@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})},    //指定以某种规则只扫描哪些组件
        useDefaultFilters = false    //includeFilters必须配合useDefaultFilters = false(默认值是true)来使用*/
        )        

public class MainConfig {
    
    //给容器注册一个Bean;类型为返回值类型(bean的id默认是用方法名作为id)
    //@Bean("")增加内容后指定bean的id
    @Bean("person")
    public Person person() {
        return new Person("张三", 19);
    }
}

2、在测试类中写测试方法

    /**
     * 测试Scope注解设置组件作用域
     */
    @Test
    public void test02() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person p1 = (Person) applicationContext.getBean("person");
        Person p2 = (Person) applicationContext.getBean("person");
        System.out.println(p1 == p2);
    }

测试后输出为

 由此说明从容器中取出的Person为同一个对象,即注册的person的scope(作用域)为singleton(单例)

spring注册的组件默认为单例模式

3、修改主配置类person组件的作用域为prototype(多例模式)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Scope;

import com.atguigu.bean.Person;

//配置类==配置文件
@Configuration        //告诉Spring这是一个配置类
@ComponentScan(value="com.atguigu",        //指定要扫描的包
        excludeFilters= {@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})}  //指定以某种规则排除扫描哪些组件
        /*includeFilters= {@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})},    //指定以某种规则只扫描哪些组件
        useDefaultFilters = false    //includeFilters必须配合useDefaultFilters = false(默认值是true)来使用*/
        )        

public class MainConfig {
    
    //给容器注册一个Bean;类型为返回值类型(bean的id默认是用方法名作为id)
    //@Bean("")增加内容后指定bean的id
    @Bean("person")
    @Scope("prototype")        //多例模式
    public Person person() {
        return new Person("张三", 19);
    }
}

再次运行测试方法后结果为:

 则说明作用域为propotype的组件每次从容器中取出都是一个新的对象

在注解类中设置scope也是一样的方式:

 4、单例对象懒加载设置(懒加载只针对单例对象)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;

import com.atguigu.bean.Person;

//配置类==配置文件
@Configuration        //告诉Spring这是一个配置类
@ComponentScan(value="com.atguigu",        //指定要扫描的包
        excludeFilters= {@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})}  //指定以某种规则排除扫描哪些组件
        /*includeFilters= {@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})},    //指定以某种规则只扫描哪些组件
        useDefaultFilters = false    //includeFilters必须配合useDefaultFilters = false(默认值是true)来使用*/
        )        

public class MainConfig {
    
    //给容器注册一个Bean;类型为返回值类型(bean的id默认是用方法名作为id)
    //@Bean("")增加内容后指定bean的id
    @Bean("person")
    @Lazy                        //单例对象懒加载,第一次获取的时候才创建,而不是IOC容器初始化时创建
    public Person person() {
        return new Person("张三", 19);
    }
}

总结:

  singleton :表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例

    单例对象在没有设置懒加载时候是在springIOC容器创建时就创建(只创建一次)

    设置懒加载之后springIOC容器创建时不创建,而是在第一次获取该单例对象时才创建(只创建一次,懒加载只对象单例对象有效)


  prototype:表示每次获得bean都会生成一个新的对象

    多例对象是在每次获取的时候才创建
  request : 表示在一次http请求内有效(只适用于web应用)
  session : 表示在一个用户会话内有效(只适用于web应用)
  globalSession : 表示在全局会话内有效(只适用于web应用)

在多数情况,我们只会使用singleton和prototype两种scope,如果在spring配置文件内未指定scope属性,默认为singleton。

  单例的原因有二:

    1、为了性能。

    2、不需要多例。

多例主要用在controller中

原文地址:https://www.cnblogs.com/lyh233/p/12435383.html