JavaEE进阶第四课:Bean 作用域和生命周期
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
上篇文章介绍了Spring更简单的对象存储和取出这篇文章我们将会介绍Bean 作用域和生命周期
目录
1.作用域
1.1引例
首先这里的作用域和我们之前java学到变量的作用域可能有点不一样。我们之前学习的变量作用域指的是该变量的可使用范围比如
{
{
int a=0;
}//2
}//1
a变量只在括号2中生效。但是Bean的作用域指的是
- Bean在Spring框架(项目)里面的某种行为模式
具体什么意思呢我们先看例子
有一个公共的Bean供A和B两个类使用假设这个Bean里面有个属性为value=ikunA第一次使用时拿到value=ikun待B使用时他偷偷改成了value=只因A下一次使用时就拿到了value=只因但是预期value=ikun啊从而导致了程序出现错误。
说好一起当ikun你却偷偷开了团
用代码怎么演示呢
@Controller
@Data
public class Ikun {
private String name="ikun";
}
@Controller
public class A {
@Autowired
private Ikun ikun;
public void show(){
System.out.println(ikun.getName());//我是ikun
}
}
@Controller
public class B {
@Autowired
private Ikun ikun;
public void show(){
ikun.setName("只因");//偷偷开团
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context=
new ClassPathXmlApplicationContext("spring-config.xml");
A a=context.getBean("a",A.class);
System.out.println("A第一次使用Ikun:");
a.show();
B b=context.getBean("b",B.class);
System.out.println("B偷偷开团修改Ikun");
b.show();
System.out.println("A第二次使用Ikun:");
a.show();
}
}
注意这里使用了@Data注解属于lombok插件可以帮我们处理setget等等方法喜欢可以去了解以下
运行得到结果
首先怎么处理这样的问题呢我们需要先知道原因。
原因是Bean默认的作用域是单例状态也就是所有类用的都是同一个对象。可能会有人问为什么默认是单例模式呢因为对于单例模式以前学过懒汉饿汉等等我们知道可以提高代码的性能。那怎么修改Bean的模式呢修改之前我们要先知道有哪些模式。
1.2Bean的六种作用域
- singleton单例作⽤域
- prototype原型作⽤域多例作⽤域
- request请求作⽤域
- session回话作⽤域
- application全局作⽤域
- websocketHTTP WebSocket 作⽤域
后四种都属于SpringMVC里面的值普通的Spring只有前两种本文只说前两种。
第一种已经说明着重解释第二种
prototype原型作⽤域多例作⽤域
这个与单例作用域恰恰相反每一次装配即@AutoWired都是新的对象实例也就是一个类修改Bean不会影响另一个类的Bean。
那怎么修改上面例子的Bean为该模式呢
1.3设置作用域
使用@Scope 标签就可以⽤来声明 Bean 的作⽤域
为Ikun类添加注解
//或者 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope("prototype")
@Controller
@Data
public class Ikun {
private String name="ikun";
}
得到结果
很明显开团失败了
小结
@Scope 标签既可以修饰⽅法也可以修饰类(上面就是修饰类)
@Scope 有两种设置⽅式
- 直接设置值@Scope(“prototype”)//适合记得住单词
- 使⽤枚举设置@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)//idea会有提示更方便
2.生命周期
解释生命周期之前必须要先了解Spring的执行流程
2.1Spring 执行流程
这个我JavaEE第二课就介绍过这里我直接给出流程
Bean 执行流程Spring 执行流程启动 Spring 容器 -> 实例化 Bean读取配置文件分配内存空间初始化 -> Bean 注册到 Spring 中存操作 -> 将 Bean 装配到需要的类中取操作)
这里可能会出一道面试题
2.2Bean的生命周期
生命周期指的是有个对象从诞生到销毁的整个生命过程Bean的生命周期注意分为以下五部分
- 实例化Bean为Bean分配内存空间ex:拿到毛坯房
- 设置属性Bean注入和装配ex:购买装修材料
- 进行初始化工作
实现了各种 Aware 通知的方法如 BeanNameAware、BeanFactoryAware、
ApplicationContextAware 的接口方法ex:通知装修工人
执行 BeanPostProcessor 初始化前置方法ex:工人制定装修方案
执行 @PostConstruct 初始化方法依赖注入操作之后被执行
执行自己指定的 init-method 方法如果有指定的话ex:开始装修
执行 BeanPostProcessor 初始化后置方法ex:处理装修后现场 - 使用Bean ex:住房
- 销毁Bean ex:拆迁房子被击碎
个人而言对于第二点设置属性Bean注入和装配如果有疑问的。看以下代码便知
@Controller
public class B {
@Autowired //这一步就是设置属性
private Ikun ikun;
public void show(){
ikun.setName("只因");//偷偷开团
}
}
看到这里我们可以思考一个问题
上面五个部分中2和3能不能颠倒顺序
显然是不能的因为可能第三步中会用到第二步的设置好的属性Bean如果颠倒就会导致出现空指针异常因为Bean还没有注入和装配。
结束语
那么今天的第四课就到这里下节课会进入SpringBoot的学习喜欢的话还请多多为我投票吧doge