spring注解開發:bean的作用域與懶加載


1、bean的作用域


1、新建一個maven工程,添加如下依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

2,新建一個實體Person類

package com.yefengyu.annotation.bean;

public class Person
{
    private String name;

    private Integer age;

    public Person()
    {
    }

    public Person(String name, Integer age)
    {
        this.name = name;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public Integer getAge()
    {
        return age;
    }

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

    @Override
    public String toString()
    {
        return "Person{" +
               "name='" + name + '\'' +
               ", age=" + age +
               '}';
    }
}

3、新建一個配置類

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MainConfig
{
    @Bean
    public Person person()
    {
        return new Person("張三", 20);
    }
}

4、測試

public static void main(String[] args)
{
    ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
    Person person1 = (Person)ctx.getBean("person");
    Person person2 = (Person)ctx.getBean("person");
    System.out.println(person1 == person2); //true
}

上面結果看出從容器多次獲取一個bean,其實都是同一個對象,這是由於bean的作用域是 單實例 造成的。

prototype:多實例的:ioc容器啟動並不會去調用方法創建對象放在容器中。每次獲取的時候才會調用方法創建對象;
singleton:單實例的(默認值):ioc容器啟動會調用方法創建對象放到ioc容器中。以后每次獲取就是直接從容器中拿,
request:同一次請求創建一個實例
session:同一個session創建一個實例

此外我們可以修改配置類,增加打印,方便觀察:

@Configuration
public class MainConfig
{
    @Bean
    public Person person()
    {
        System.out.println("創建Person對象");
        return new Person("張三", 20);
    }
}

我們再次運行上面的測試代碼發現 創建Person對象 這句只打印了一次。

5、使用方式:Scope注解

@Configuration
public class MainConfig
{
    @Bean
    @Scope("prototype")
    public Person person()
    {
        System.out.println("創建Person對象");
        return new Person("張三", 20);
    }
}

注意:Scope注解是對bean的作用域進行修飾,可以修改bean的作用域,可以和@Bean注解與@Component系列注解一起使用。

我們再次運行上面的測試代碼發現 創建Person對象 這句打印了兩次。並且兩個對象不相同,使用 == 比較返回 false.

Scope中的值可以使用上面的字符串,例如prototype,也可以使用

  • ConfigurableBeanFactory.SCOPE_PROTOTYPE
  • ConfigurableBeanFactory.SCOPE_SINGLETON
  • WebApplicationContext.SCOPE_REQUEST
  • WebApplicationContext.SCOPE_SESSION

2、懶加載


專門針對單實類,也叫延遲加載。

@Configuration
public class MainConfig
{
    @Bean
    public Person person()
    {
        System.out.println("創建Person對象");
        return new Person("張三", 20);
    }
}

單實例bean:默認在容器啟動的時候創建對象;

AnnotationConfigApplicationContext ctx =new AnnotationConfigApplicationContext(MainConf.class);

下面這段測試代碼並沒有使用到 person ,但是通過打印我們可以看出已經加載了Person對象。

public static void main(String[] args)
{
    ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
    String[] names = ctx.getBeanDefinitionNames();
    for (String name : names)
    {
        System.out.println(name);
    }
}
創建Person對象
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person

現在我們加上一個注解@Lazy

@Configuration
public class MainConfig
{
    @Bean
    @Lazy
    public Person person()
    {
        System.out.println("創建Person對象");
        return new Person("張三", 20);
    }
}

此時再次測試,得出的結果如下

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person

說明在延遲加載的情況下,如果沒有使用到bean,那么就不會在容器真正創建一個對象(沒有打印 :創建Person對象 ),現在我們在測試代碼加上對 person對象的獲取。

public static void main(String[] args)
{
    ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
    String[] names = ctx.getBeanDefinitionNames();
    for (String name : names)
    {
        System.out.println(name);
    }
    Person person= (Person)ctx.getBean("person");
}
得到的結果如下,注意打印順序
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person 創建Person對象

懶加載歸納:容器啟動不創建對象。第一次使用(獲取)Bean時創建對象,並初始化


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM