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时创建对象,并初始化

spring注解开发:bean的作用域与懒加载的更多相关文章

  1. Spring注解驱动开发02(作用域和懒加载)

    Spring中bean的作用域 默认情况下,Spring只为每个在IOC容器里声明的bean创建唯一一个实例,整个IOC容器范围内都能共享该实例:所有后续的getBean()调用和bean引用都将返回 ...

  2. Spring Boot JPA Entity Jackson序列化触发懒加载的解决方案

    Spring Jpa这项技术在Spring 开发中经常用到. 今天在做项目用到了Entity的关联懒加载,但是在返回Json的时候,不管关联数据有没有被加载,都会触发数据序列化,而如果关联关系没有被加 ...

  3. iOS 开发——实用技术Swift篇&Swift 懒加载(lazy)

    Swift 懒加载(lazy) 在程序设计中,我们经常会使用 * 懒加载 * ,顾名思义,就是用到的时候再开辟空间,比如iOS开发中的最常用控件UITableView,实现数据源方法的时候,通常我们都 ...

  4. iOS 开发UI篇 -- 懒加载学习

    1. 懒加载基本 懒加载--也称为延迟加载,即在需要的时候才加载( 效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实 ...

  5. 【Spring注解驱动开发】使用@Lazy注解实现懒加载

    写在前面 Spring在启动时,默认会将单实例bean进行实例化,并加载到Spring容器中.也就是说,单实例bean默认在Spring容器启动的时候创建对象,并将对象加载到Spring容器中.如果我 ...

  6. 「新特性」Spring Boot 全局懒加载机制了解一下

    关于延迟加载 在 Spring 中,默认情况下所有定的 bean 及其依赖项目都是在应用启动时创建容器上下文是被初始化的.测试代码如下: @Slf4j @Configuration public cl ...

  7. Spring IOC - 控制反转(依赖注入) - 懒加载机制

    懒加载机制 Spring默认会在容器初始化的过程中,解析xml,并将单例的bean创建并保存到map中,这样的机制在bean比较少的时间问题不大,但一旦bean非常多时,Spring需要在启动的过程中 ...

  8. hibernate+spring mvc, 解决hibernate 对象懒加载 json序列化问题

    引用地址 在使用Spring MVC时,@ResponseBody 注解的方法返回一个有懒加载对象的时候出现了异常,以登录为例: @RequestMapping("login") ...

  9. hibernate+spring mvc,解决hibernate对象懒加载,json序列化失败

    在使用spring MVC时,@ResponseBody 注解的方法返回一个有懒加载对象的时候出现了异常,以登录为例: @RequestMapping("login") @Resp ...

随机推荐

  1. ecshop 广告调用的几种方式

    1,ECSHOP后台设置广告更换 前台调用 {insert name='ads' id=2 num=1} id值表达广告位置的id.num表示数量 2,在代码加函数 function getads($ ...

  2. android 完全退出应用程序(经过严格验证)

    今天解决了如何彻底结束Android应用程序的方法.网上有很多的参考方法,什么finish():android.os.Process.killProcess(android.os.Process.my ...

  3. 华为Android手机打开Log

    华为Android手机打开Log, 显示日志方法 今天在华为u8650上调试应用程序时,发现Eclipse的log始终无法显示,在网上找了好多资料,甚至stack overflow也查了,最后终于找到 ...

  4. 【学习总结】认识MVC

    参考链接: 菜鸟教程-MVC模式 CSDN:浅谈MVC架构-你到底有什么本事 目录: 一.什么是MVC 1.概念 MVC全名是Model View Controller,是模型(model)-视图(v ...

  5. 基于TensorFlow Object Detection API进行迁移学习训练自己的人脸检测模型(二)

    前言 已完成数据预处理工作,具体参照: 基于TensorFlow Object Detection API进行迁移学习训练自己的人脸检测模型(一) 设置配置文件 新建目录face_faster_rcn ...

  6. linux典型应用对系统资源使用的特点

  7. 微信小程序(2)--下拉刷新和上拉加载更多

    下拉刷新 1.首先在.json文件中配置(如果在app.json文件中配置,那么整个程序都可以下拉刷新.如果写在具体页面的.json文件中,那么就是对应的页面下拉刷新.) 具体页面的.json文件: ...

  8. Nexus搭建Maven私服中央仓库

    一.概述 1.概要 现在的项目基本都是用Maven来管理工程,这样一来在公司内容搭建一个私服就非常有必要了,这样一来可以管理公司内部用的JAR包,也可以管理第三方的各种JAR来,以免每次都要从外网的仓 ...

  9. python常用函数 S

    slice(int,int) 切片,可以为切片命名增加可读性. 例子: sorted(iterable, key) 排序,支持传入参数,例如通过itemgetter传入参数(itemgetter可以传 ...

  10. Hadoop的基础命令

    首次使用Hadoop时,格式化文件系统命令:hdfs namenode -format 启动HDFS:start-dfs.sh 启动YARN:start-all.sh start-all.sh等价于s ...