上篇文章介绍了Spring更简单的对象存储和取出,这篇文章我们将会介绍Bean 作用域和生命周期
首先这里的作用域和我们之前java学到变量的作用域可能有点不一样。我们之前学习的变量作用域指的是该变量的可使用范围,比如:
{{int a=0;}//2
}//1
a变量只在括号2中生效。但是Bean的作用域指的是:
具体什么意思呢,我们先看例子:
有一个公共的Bean供A和B两个类使用,假设这个Bean里面有个属性为value=ikun,A第一次使用时拿到value=ikun,待B使用时他偷偷改成了value=只因,A下一次使用时就拿到了value=只因,但是预期value=ikun啊,从而导致了程序出现错误。
说好一起当ikun,你却偷偷开了团
用代码怎么演示呢?
@Controller
@Data
public class Ikun {private String name="ikun";
}@Controller
public class A {@Autowiredprivate Ikun ikun;public void show(){System.out.println(ikun.getName());//我是ikun}
}@Controller
public class B {@Autowiredprivate 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插件,可以帮我们处理set,get等等方法,喜欢可以去了解以下
运行得到结果:
首先怎么处理这样的问题呢?我们需要先知道原因。
原因是Bean默认的作用域是单例状态,也就是所有类用的都是同一个对象。可能会有人问,为什么默认是单例模式呢?因为对于单例模式(以前学过懒汉,饿汉等等),我们知道可以提高代码的性能。那怎么修改Bean的模式呢?修改之前,我们要先知道有哪些模式。
后四种都属于SpringMVC里面的值,普通的Spring只有前两种,本文只说前两种。
第一种已经说明,着重解释第二种
prototype:原型作⽤域(多例作⽤域)
这个与单例作用域恰恰相反,每一次装配(即@AutoWired)都是新的对象实例,也就是一个类修改Bean不会影响另一个类的Bean。
那怎么修改上面例子的Bean为该模式呢?
使用@Scope 标签就可以⽤来声明 Bean 的作⽤域
为Ikun类添加注解
//或者 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope("prototype")
@Controller
@Data
public class Ikun {private String name="ikun";
}
得到结果:
很明显,开团失败了
小结:
@Scope 标签既可以修饰⽅法也可以修饰类(上面就是修饰类)
@Scope 有两种设置⽅式:
解释生命周期之前,必须要先了解Spring的执行流程
这个我JavaEE第二课就介绍过,这里我直接给出流程:
Bean 执行流程(Spring 执行流程):启动 Spring 容器 -> 实例化 Bean(读取配置文件,分配内存空间,初始化) -> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取操作)
这里可能会出一道面试题:
生命周期指的是有个对象从诞生到销毁的整个生命过程,Bean的生命周期注意分为以下五部分:
个人而言,对于第二点设置属性(Bean注入和装配)如果有疑问的。看以下代码便知:
@Controller
public class B {@Autowired //这一步就是设置属性private Ikun ikun;public void show(){ikun.setName("只因");//偷偷开团}
}
看到这里我们可以思考一个问题:
上面五个部分中,2和3能不能颠倒顺序?
显然是不能的,因为可能第三步中会用到第二步的设置好的属性Bean,如果颠倒就会导致出现空指针异常,因为Bean还没有注入和装配。
那么今天的第四课就到这里,下节课会进入SpringBoot的学习,喜欢的话还请多多为我投票吧(doge)