【JavaEE进阶】 Bean的作用域与生命周期

简介: 【JavaEE进阶】 Bean的作用域与生命周期

🍃Bean的作用域

Bean的作⽤域是指Bean在Spring框架中的某种⾏为模式.

比如单例作⽤域:表⽰ Bean 在整个Spring 中只有⼀份, 它是全局共享的.那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值.

在Spring中⽀持6种作⽤域,后4种在Spring MVC环境才⽣效

  1. singleton:单例作⽤域
  2. prototype:原型作⽤域(多例作⽤域)
  3. request:请求作⽤域
  4. session:会话作⽤域
  5. Application: 全局作⽤域
  6. websocket:HTTP WebSocket 作⽤域
作⽤域 说明
singleton 每个Spring IoC容器内同名称的bean只有⼀个实例(单例)(默认)
prototype 每次使⽤该bean时会创建新的实例(⾮单例)
request 每个HTTP 请求⽣命周期内,创建新的实例(web环境中)
session 每个HTTP Session⽣命周期内,创建新的实例(web环境中)
application 每个ServletContext⽣命周期内,创建新的实例(web环境中)
websocket 每个WebSocket⽣命周期内,创建新的实例(web环境中)

🚩作用域的使用

简单使用如下:

首先我们准备一个 Dog 类如下:

public class Dog {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

接下来我们定义几个不同作用域的 Bean

@Component
public class DogBean {
    @Bean
    public Dog dog() {
        Dog dog = new Dog();
        dog.setName("旺财");
        return dog;
    }
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Dog singleDog(){
        Dog dog = new Dog();
        return dog;
    }
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Dog prototypeDog(){
        Dog dog = new Dog();
        return dog;
    }
    @Bean
    @RequestScope
    public Dog requestDog() {
        Dog dog = new Dog();
        return dog;
    }
    @Bean
    @SessionScope
    public Dog sessionDog() {
        Dog dog = new Dog();
        return dog;
    }
    @Bean
    @ApplicationScope
    public Dog applicationDog() {
        Dog dog = new Dog();
        return dog;
    }
}

需要注意的是

@RequestScope 等同于

@Scope(value =WebApplicationContext.SCOPE_REQUEST, proxyMode=ScopedProxyMode.TARGET_CLASS)

@SessionScope 等同于

@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.TARGET_CLASS)

@ApplicationScope 等同于 @Scope(value=WebApplicationContext.SCOPE_APPLICATION,proxyMode=ScopedProxyMode.TARGET_CLASS)

proxyMode⽤来为springbean设置代理.

proxyMode = ScopedProxyMode.TARGET_CLASS

表⽰这个Bean基于CGLIB实现动态代理.

Request,session和application作⽤域的Bean需要设置proxyMode

接下来我们再写一些程序进行测试,测试不同作⽤域的Bean取到的对象是否⼀样,测试程序如下:

@RestController
public class DogController {
    @Autowired
    private Dog singleDog;
    @Autowired
    private Dog prototypeDog;
    @Autowired
    private Dog requestDog;
    @Autowired
    private Dog sessionDog;
    @Autowired
    private Dog applicationDog;
    @Autowired
    private ApplicationContext applicationContext;
    @RequestMapping("/single")
    public String single(){
        Dog contextDog = (Dog)applicationContext.getBean("singleDog");
        return "dog:"+singleDog.toString()+"|-- --|contextDog:"+contextDog;
    }
    @RequestMapping("/prototype")
    public String prototype(){
        Dog contextDog = (Dog)applicationContext.getBean("prototypeDog");
        return "dog:"+prototypeDog.toString()+"|-- --|contextDog:"+contextDog;
    }
    @RequestMapping("/request")
    public String request(){
        Dog contextDog = (Dog)applicationContext.getBean("requestDog");
        return
                "dog:"+requestDog.toString()+"|-- --|contextDog:"+contextDog.toString();
    }
    @RequestMapping("/session")
    public String session(){
        Dog contextDog = (Dog)applicationContext.getBean("sessionDog");
        return "dog:"+sessionDog.toString()+"|-- --|contextDog:"+contextDog.toString();
    }
    @RequestMapping("/application")
    public String application(){
        Dog contextDog = (Dog)applicationContext.getBean("applicationDog");
        return "dog:"+applicationDog.toString()+"|-- --|contextDog:"+contextDog.toString();
    }
}

🚩观察Bean的作用域

接下来我们来进行访问

🎈单例作用域

多次访问,得到的都是同⼀个对象,并且 @Autowired 和applicationContext.getBean() 也是同⼀个对象.

🎈多例作用域

观察ContextDog,每次获取的对象都不⼀样(注⼊的对象在Spring容器启动时,就已经注⼊了,所以多次请求也不会发⽣变化)

🎈请求作用域

在⼀次请求中, @Autowired 和 applicationContext.getBean() 也是同⼀个对象.但是每次请求,都会重新创建对象

🎈会话作⽤域

在⼀个session中,多次请求,获取到的对象都是同⼀个.

换⼀个浏览器访问,发现会重新创建对象.(另⼀个Session)

🎈Application作⽤域

在⼀个应⽤中,多次访问都是同⼀个对象

Application scope就是对于整个web容器来说,bean的作⽤域是ServletContext级别的.

这个和singleton有点类似,区别在于:Application scope是ServletContext的单例,singleton是⼀个ApplicationContext的单例.

在⼀个web容器中ApplicationContext可以有多个

🎄Bean的⽣命周期

⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程,我们把这个过程就叫做⼀个对象的⽣命周期.

Bean的⽣命周期分为以下5个部分:

  1. 实例化(为Bean分配内存空间)
  2. 属性赋值(Bean注⼊和装配,⽐如 @AutoWired )
  3. 初始化
  • 执⾏各种通知,如 BeanNameAware ,BeanFactoryAware ,ApplicationContextAware 的接⼝⽅法.
  • 执⾏初始化⽅法
  • xml定义 init-method
  • 使⽤注解的⽅式 @PostConstruct
  • 执⾏初始化后置⽅法( BeanPostProcessor )
  1. 使⽤Bean
  2. 销毁Bean
  • 销毁容器的各种⽅法,如 @PreDestroy , DisposableBean 接⼝⽅法, destroymethod.

实例化和属性赋值对应构造⽅法和setter⽅法的注入.

初始化和销毁是用户能⾃定义扩展的两个阶段,可以在实例化之后,类加载完成之前进⾏⾃定义"事件"处理.

⽐如我们现在需要买⼀栋房⼦,那么我们的流程是这样的:

  1. 先买房(实例化,从⽆到有)
  2. 装修(设置属性)
  3. 买家电,如洗⾐机,冰箱,电视,空调等([各种]初始化,可以⼊住);
  4. ⼊住(使⽤Bean)
  5. 卖房(Bean销毁)

执行流程如下图所示:

⭕总结

关于《【JavaEE进阶】 Bean的作用域与生命周期》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

相关文章
|
5月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
62 0
|
XML Java 数据格式
Spring中Bean的作用域与生命周期
Spring中Bean的作用域与生命周期
66 0
|
6月前
|
XML Java 数据格式
Spring框架学习 -- Bean的生命周期和作用域
Spring框架学习 -- Bean的生命周期和作用域
54 2
|
6月前
|
Java 容器 Spring
Javaweb之SpringBootWeb案例之 Bean管理的Bean作用域详细的解析
Javaweb之SpringBootWeb案例之 Bean管理的Bean作用域详细的解析
40 0
|
6月前
|
Java 开发者 容器
SpringBoot:详解Bean生命周期和作用域
SpringBoot:详解Bean生命周期和作用域
303 0
|
6月前
|
XML 缓存 Java
Spring5源码(9)-Bean的作用域和生命周期
Spring5源码(9)-Bean的作用域和生命周期
47 0
|
6月前
|
Java Spring
spring Bean的作用域和生命周期
spring Bean的作用域和生命周期
|
Java Spring 容器
探究Spring Bean的六种作用域:了解适用场景和使用方式
探究Spring Bean的六种作用域:了解适用场景和使用方式
|
XML 存储 缓存
Spring 中 Bean 的作用域以及生命周期
Spring 中 Bean 的作用域以及生命周期
154 0
|
XML Java 数据格式
【Spring】Bean 的作用域和生命周期
1. Bean 的作用域 1.1 通过一个案例来看 Bean 作用域的问题 1.2 作用域的定义 1.3 Spring Bean 支持的作用域(未介绍完全) 1.4 修改 Bean 的作用域 1.5 Bean 执行流程 2. Bean 的生命周期 2.1 Bean 的生命周期分为以下 5 大部分 2.1.1 实例化 Bean(为 Bean 分配内存空间) 2.1.2 设置属性(Bean 注入和装配) 2.1.3 Bean 初始化 2.1.4 Bean 使用 2.1.5 销毁 Bean 2.2 Bean 的生命周期执行流程 2.3 生命周期演示
165 1