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

相关文章
|
6月前
|
前端开发 Java 开发者
Bean的生命周期和作用域
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
Bean 作用域和生命周期
Bean 作用域和生命周期
|
6月前
|
Java 容器 Spring
Javaweb之SpringBootWeb案例之 Bean管理的Bean作用域详细的解析
Javaweb之SpringBootWeb案例之 Bean管理的Bean作用域详细的解析
41 0
|
Java Spring
案例06 Bean的作用域案例
分别使用singleton和prototype作用域创建Bean实例,比较singleton和prototype作用域的区别。
45 0
|
6月前
|
Java 开发者 容器
SpringBoot:详解Bean生命周期和作用域
SpringBoot:详解Bean生命周期和作用域
308 0
|
6月前
|
XML 缓存 Java
Spring5源码(9)-Bean的作用域和生命周期
Spring5源码(9)-Bean的作用域和生命周期
48 0
|
6月前
|
缓存 前端开发 Java
面试题:说说你对Bean作用域的理解和使用?
面试题:说说你对Bean作用域的理解和使用?
53 0