搜索
您的当前位置:首页正文

Spring注解——使用@Scope和@Lazy设置作用域和实现

来源:二三娱乐

1.默认情况下 spring 容器中都是单实例。

import io.mieux.bean.Person;
import io.mieux.BeanConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

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

运行结果:

true

2.如果需要多实例,则需要使用 @Scope 注解,并将其 value 设为 ConfigurableBeanFactory.SCOPE_PROTOTYPE。

package io.mieux.config;

import io.mieux.bean.Person;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Person person() {
        return new Person("zhangsan", 28);
    }
}

运行效果:

false

3.singleton 和 prototype 的实例创建的时间是不一样的。singleton 在容器初始化的时候就被创建,而 prototype 则在需要获取实例的时候才被创建。可以通过在 BeanConfig 配置类创建 Person 实例时,增加一行输出来验证。

首先是 singleton 的验证,将 @Scope 的 value 修改为 ConfigurableBeanFactory.SCOPE_SINGLETON,并且暂时注释掉获取 person 实例部分的代码。

package io.mieux.config;

import io.mieux.bean.Person;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Person person() {
        System.out.println("创建 Person 实例");
        return new Person("zhangsan", 28);
    }
}

import io.mieux.BeanConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App03 {
    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(BeanConfig.class);
//        Person person1 = applicationContext.getBean(Person.class);
//        Person person2 = applicationContext.getBean(Person.class);
//        System.out.println(person1 == person2);
    }
}

运行效果:

创建 Person 实例

接着是 prototype 的验证,将 @Scope 的 value 修改为 ConfigurableBeanFactory.SCOPE_PROTOTYPE,先依然保持注释掉获取 person 实例部分的代码。

package io.mieux.config;

import io.mieux.bean.Person;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Person person() {
        System.out.println("创建 Person 实例");
        return new Person("zhangsan", 28);
    }
}

运行之后并没有输出任何信息,说明了在容器初始化的时并没有创建实例。

将获取 person 实例部分的代码取消注释。

import io.mieux.config.BeanConfig;
import io.mieux.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

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

运行效果:

创建 Person 实例
创建 Person 实例
false

4.spring 默认使用的是 singleton,也就是刚才所说的,单实例,并且在容器初始化的时候就被创建。如果希望和 prototype 一样,在第一次使用实例时才创建,也就是常说的懒加载,就需要使用 @Lazy 注解。

在 BeanConfig 配置类的 person 方法上增加 @Lazy 注解。

package io.mieux.config;

import io.mieux.bean.Person;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;


@Configuration
public class BeanConfig {

    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    @Lazy
    public Person person() {
        System.out.println("创建 Person 实例");
        return new Person("zhangsan", 28);
    }
}

先注释掉获取 person 实例部分的代码。

import io.mieux.config.BeanConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App03 {
    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(BeanConfig.class);
//        Person person1 = applicationContext.getBean(Person.class);
//        Person person2 = applicationContext.getBean(Person.class);
//        System.out.println(person1 == person2);
    }
}

运行之后并没有输出任何信息,说明了在容器初始化的时并没有创建实例。

接着取消掉获取 person1 实例的注释:

import io.mieux.config.BeanConfig;
import io.mieux.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App03 {
    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(BeanConfig.class);
        Person person1 = applicationContext.getBean(Person.class);
//        Person person2 = applicationContext.getBean(Person.class);
//        System.out.println(person1 == person2);
    }
}

运行效果:

创建 Person 实例

运行结果就表明了,在第一次获取 person 实例时,才会创建 person 实例。

Top