@Scope-设置组件作用域

@Scope-设置组件作用域

如果不使用@Scope设置组件的作用域, 那么默认组件作用域都是singleton(单实例的)

首先我们来看一下@Scope都有哪几种作用域:

查看@Scope源码, 主要关注value属性值的取值:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
	/**
	 * Alias for {@link #scopeName}.
	 * @see #scopeName
	 */
	@AliasFor("scopeName")
	String value() default "";

	/**
	 * Specifies the name of the scope to use for the annotated component/bean.
	 * <p>Defaults to an empty string ({@code ""}) which implies
	 * {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
	 * @since 4.2
	 * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
	 * @see ConfigurableBeanFactory#SCOPE_SINGLETON
	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
	 * @see #value
	 */
	@AliasFor("value")
	String scopeName() default "";
    ...
}

可以看到取值主要分为四种:

* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
  1. prototype : 多实例的
  2. singleton : 单实例的
  3. request : 同一个请求创建一个实例
  4. session : 同一个Session创建一个实例

可以发现request和session都是在web工程中使用的

如果作用域是单实例, 那么默认是IOC容器启动的时候就会创建单例对象放到IOC容器中的单例map中
package com.ffyc.spring.config;

import com.ffyc.spring.model.Person;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan(value = "com.ffyc.spring")
public class PersonConfig {

    @Bean
    public Person getPerson() {
        System.out.println("创建person实例...");
        return new Person();
    }
}

测试:

package com.ffyc.spring.test;

import com.ffyc.spring.config.PersonConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test3 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(PersonConfig.class);
    }
}

可以看到, 我们只是启动IOC容器的时候就调用了PersonConfig中的getPerson()方法

如果作用域是多实例, 那么默认不是在IOC容器启动的时候创建实例, 而是在每次使用IOC容器调用getBean()方法获取该实例的时候就调用该方法创建一个对象并返回
  • 值得注意的是 : 多实例对象是不会存储在IOC容器中的, 如果是多实例对象, 那么就是每次需要使用的时候就创建一个并返回, 并不会将该多实例对象放到IOC容器中
package com.ffyc.spring.config;

import com.ffyc.spring.model.Person;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan(value = "com.ffyc.spring")
public class PersonConfig {

    @Bean
    @Scope("prototype")
    public Person person() {
        System.out.println("创建person实例...");
        return new Person();
    }
}

测试:

package com.ffyc.spring.test;

import com.ffyc.spring.config.PersonConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test3 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(PersonConfig.class);
    }
}

发现启动IOC容器的时候确实没用创建该实例对象

测试:

package com.ffyc.spring.test;

import com.ffyc.spring.config.PersonConfig;
import com.ffyc.spring.model.Person;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test3 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(PersonConfig.class);
        System.out.println(annotationConfigApplicationContext.getBean("person"));
    }
}

发现确实是使用IOC容器调用getBean()方法的时候创建的多实例对象

扩展 : 懒加载(延时加载)

如果是作用域是单例, 添加@Lazy注解之后也就是只有使用IOC容器调用getBean()方法获取该单例实例的时候才调用对应的方法创建该实例, 而不是容器启动的时候就创建该实例
package com.ffyc.spring.config;

import com.ffyc.spring.controller.MyTypeFilter;
import com.ffyc.spring.model.Person;
import org.springframework.context.annotation.*;

@Configuration
@ComponentScan(value = "com.ffyc.spring")
public class PersonConfig {

    @Bean
    @Lazy
    @Scope("singleton")
    public Person person() {
        System.out.println("创建person实例...");
        return new Person();
    }
}

测试:

package com.ffyc.spring.test;

import com.ffyc.spring.config.PersonConfig;
import com.ffyc.spring.model.Person;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test3 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(PersonConfig.class);
    }
}

发现确实不是IOC容器启动的时候完成的创建实例

测试:

package com.ffyc.spring.test;

import com.ffyc.spring.config.PersonConfig;
import com.ffyc.spring.model.Person;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test3 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(PersonConfig.class);
        System.out.println(annotationConfigApplicationContext.getBean("person"));
    }
}

发现确实是IOC第一次调用getBean()方法获取该实例的时候完成的创建

bean作用域如果为单例, 那么创建之后会放到IOC容器的单例map中, 下次通过IOC容器获取该单例对象的时候, IOC容器会将对应的单例对象直接返回, 不会重新创建
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值