Bean作用域、生命周期

bean作用域

Bean 的作用域指bean在spring框架的某种行为模式;bean的6种作用域分别是以下:
1:单例(Singleton)作用域
2:原型(Prototype)作用域
3:请求(Request)作用域
4:会话(Session)作用域:
5:全局(application)作用域
6:HTTP WebSockect 作用域

编写一个测试用例体会一下默认是什么行为模式:

先回顾spring的创建:先创建maven项目;在pom.mxl添加spring依赖;然后添加配置文件;配置扫描路径。等到spring boot就会发现还有摩托车这种好东西;正在骑着的电动车不香了;加油只需几十秒就能跑;电动车则需要充几个小时的电。
在这里插入图片描述
我们按一个标准分层编写这些代码:user是实体;在demo下创建一个enity实体层。userBeans是创建user实例对象要存入spring放在组件里(因为这是额外的东西;我的目的是想在spring有这样一个东西);userController、userController2是分别取出spring的对象进行操作;放在控制层。APP则是启动类。

1:首先有一个user类;里面有id和name属性;使用lombok写一下tostring和get、set方法。
在这里插入图片描述

2:有一个userBeans类;这个类用来把user的一个对象存到spring中;
在这里插入图片描述

3:有一个userController2类;使用注解Autowired把刚才存在spring的对象取出来;并且这里有一个方法printUser;作用是把这个取到的对象进行name属性的修改。
在这里插入图片描述

4:还有一个userController类;在上述修改完成后用Resource再把spring的user对象取出来看看是什么结果。到底有没有被3修改。
在这里插入图片描述

3和4我们要查到结果的话;没办法在main方法使用注解获取;所以我们套娃再把userController、userController2存入spring去;我们在启动类使用三板斧的方式;取出;并执行里面的方法;就可以知道它们用注解取出的user的初始化及修改情况。
0
简单来说a=b;然后我再a=c;结果是a=c;b=c。bean作用域;默认是单例模式;因为它们指向的是同一个地方。两个变量指向同一个引用。单例性能高;反复利用;不要每次用的时候就创建。但是上述的场景不适合;bean状态会被更新。

2.原型模式:prototype;每次对bean的请求都会创建一个新的实例。就比如张三找我借笔记本;我不把我自己用的那本给他;万一你把我乱涂乱画呢;我则是自己去复印店我打印一本一模一样的给他。

3:请求(Request)作用域;每次http请求就会创建新的bean实例;类似上面的prototype(一次http请求是共享bean的)
4:会话(Session)作用域:每次session会话共享一个bean;在一个http session中就定义一个bean实例
5:全局(application)作用域:一个http servlet context 中共享一个bean
这三种只能在springMVC使用;也叫SpringWeb

6:HTTP WebSockect 作用域;这个websocket长连接;http是短连接的。只适用于Spring WebSocket项目

如何设置行为模式

设置这些行为模式:设置方式有一种;但是写法有两种。在存之前(创建)设置;而不是取的时候
写法1:@Scope(“prototype”)
写法2:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 这个就是为了避免大家写错搞出来的
设置后的结果:每一份取出来的都是新;第三行的之所以还是弼马温;因为java语法的赋值就是这样子;赋值后是指像同一个引用。
在这里插入图片描述

Bean的生命周期

Spring的执行流程:
Bean 执⾏流程(Spring 执⾏流程):启动 Spring 容器 -> 实例化 Bean(分配内存空间,从⽆到
有) -> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取操作)。
1:当你的代码到new这一步;启动spring容器。在启动类的main方法这里
在这里插入图片描述
2:启动的时候会加载配置文件:会去看你有没有配置Bean;有没有配置扫描的路径base-package。如果你配置了就根据你的配置完成bean的初始化(加载的顺序是按你xml代码顺序加载;如果你bean又依赖另一个bean;那就先加载依赖的bean)

3:如果配置了base-package;就会扫描包下所有类有没有加5大类注解;把这些类的对象注册(存)到容器中。

4:取bean;进行对象的装配。进行一个初始化。使用@Autowired、Resource注解。

bean的生命周期:bean的诞生到销毁
实例化跟初始化区别:实例化是指根据类的定义创建类的对象或实例。通过实例化可以将类的定义转换为具体的对象,使其在内存中占据一定的空间。初始化是指在对象创建后,为其属性赋予初始值或执行其他必要的操作。

大流程分五部分:
1:实例化bean;开辟内存空间
2:设置属性(bean的注入和装配)
3:bean初始化
为什么不先初始化后设置呢?因为这个属性有可能在初始化的时候被用到;比如下面的初始化方法;我在初始化的时候调用属性的方法;如果不先设置属性;那么就空指针异常。
在这里插入图片描述
初始化做的很多事情:
3.1 :实现了各种 Aware 通知的⽅法,比如bean的名字设置成功就会有一个BeanNameAware通知的方法;还有其它BeanFactoryAware、ApplicationContextAware 的接⼝⽅法;
3.2:执行初始化的前置方法; BeanPostProcessor
3.3:执行初始化方法(设置了就执行;不设置就不执行):两种实现方式(注解:@PostConstruct ;xml方式:init-method方法)
3.4:执行后置方法
4:使用bean
5:销毁bean
在这里插入图片描述

初始化方法作用:
在这里插入图片描述
例如:

import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class MyBean {
    
    

    private String data;

    @PostConstruct
    public void init() {
    
    
        // 执行初始化操作
        data = "Initialized data";
        // 其他初始化逻辑...
    }

    public String getData() {
    
    
        return data;
    }
}

代码演示:前置方法和后置方法用的比较少。
xml方式:里面很多属性;init-method就是初始化方法;destroy-methods是销毁方法。
在这里插入图片描述
实现一个BeanNameAware通知;这里的s是设置的bean的名称

在这里插入图片描述

初始化方法:得要名字一样在这里插入图片描述
在这里插入图片描述

销毁方法也是两种设置方式;xml、注解
在这里插入图片描述
使用bean的时候会自动使用这些方法;得使用 ApplicationContext子类ClassPathXmlApplicationContext去拿才能拿到;因为它的子类才有销毁方法
在这里插入图片描述

bce8477279d750d.png)

看到这里的结果会发现注解的优先级比xml高。context.destroy();这个得调用一下;销毁容器

猜你喜欢

转载自blog.csdn.net/m0_64254651/article/details/130801856
今日推荐