文章目录:一.Bean的作用域 (1)Bean作用域的含义
(2)Bean的6种作用域
二.Bean的生命周期(1)开辟内存空间
(2) 属性注入
(3)初始化
(4)使用Bean
(5)销毁Bean对象
一.作用域
作用域含义:
Bean的作用域是指Bean在Spring整个框架中的某种行为模式
下面我们通过具体的代码来演示:
我们先来创建一个User类
@Component
public class User3 {
public String name;
public int age;
}
然后通过在方法上添加Bean注解的方式在Spring容器里添加一个user对象
@Component
public class Signal {
@Bean(value = "user1")
public User3 getuser1()
{
User3 user=new User3();
user.name="小众";
user.age=7;
return user;
}
}
然后在创建两个类,然后把user对象注入到这个类里面,并且在第一个类里面我们把user的name改动
@Component
public class Useuser1 {
@Resource(name="user1")
public User3 user;
public void say()
{
System.out.println(user.name);
user.name="小莲";
System.out.println(user.name);
}
}
@Component
public class Useuser2 {
@Resource(name="user1")
public User3 user;
public void say()
{
System.out.println(user.name);
}
}
我们分别再启动类里面去运行,看一下打印结果
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
Useuser1 user=context.getBean("useuser1",Useuser1.class);
user.say();
Useuser2 user2=context.getBean("useuser2",Useuser2.class);
user2.say();
}
我们发现我们只是在Useuser1里面把user对象的名字给改了,但是Useuser2这个类里面的user对象的名字也发生了变化,这时因为默认情况下是单例模式,也就是同一个user对象只初始化一次,这个对象只有一份,是全局共享的,这两个类里面注入的对象是一份。
那可不可以两个类里面注入的对象存在多份,相互不影响呢?其实我们只需要通过添加Scope注解的方式,将模式改为多例作用域即可, prototype即为多例作用域
@Component
public class Signal {
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean(value = "user1")
public User3 getuser1()
{
User3 user=new User3();
user.name="小众";
user.age=7;
return user;
}
}
这时我们再来观察结果:
这时我们发现两个类里面注入的相同对象就不会互相影响了,
多例作用域:当我们多次注入同一个对象的时候,我们拿到的其实是最初的对象的拷贝,不同类里面注入的对象是多份,所以互不影响。
Bean的6种作用域:
1.sigleton:单例作用域 只存在一个实例,Spring默认选择改作用域
2.prototype 多例作用域: 存在多个实例,每次Bean请求都会创建新的实例,
3.request 请求作用域:每次htttp请求都会创建新的Bean实例,类似于prototype,限定于SpringMVC中使用
4.session 会话作用域: 在一个http session中,定义一个Bean实例,限定在SpringMVC中使用
5.application 全局作用域 在一个http servlet Context中,定义一个Bean实例,限定在SpringMVC中使用
6.websocket : 在一个http WebSocket的生命周期中,定义一个Bean实例,限定在Spring WebSocket中使用
单例作用域与全局作用域区别:
singleton是 Spring Core的作用域; application 是spring web 中的容器
singleton 作用 于IOC容器,而application作用于 Servelt容器
二.Bean的生命周期
1.先为Bean分配内存空间,Bean对象的实例化
2.设置属性(注入属性)
3.初始化
(1)实现了各种Aware通知的方法,比如BeanNameAware、BeanFactoryAware
(2)初始化前置方法
(3)初始化方法(两种方式,xml方式和注解方式(PostConstruct))
(4) 执行自己指定的init-method方法
(5)初始化后置方法
4.使用Bean
5.销毁Bean对象
我们具体通过代码的形式来演示Bean的生命周期这一流程
在xml文件里注册beanlife对象,并且设置了一个自定义方法init
<bean id="beanlife" class="kale.pole.Beanlife" init-method="init" > </bean>
@Component
public class Beanlife implements BeanNameAware {
自定义的方法
public void init() {
System.out.println("执行 xml初始化方法");
}
//表示具体使用Bean
public void say() {
System.out.println("执行say方法");
}
@PostConstruct //构造方法
public void myinit() {
System.out.println("执行了注解初始化方法");
}
@PreDestroy //摧毁bean
public void preDestroy() {
System.out.println("执行 preDestory方法");
}
@Override //BeanName的通知
public void setBeanName(String s) {
System.out.println("执行了setBeanName方法:" + s);
}
}
我们启动一下这个程序,注意 这里不要再用ApplicationContext这个类了,因为这个类里面没有pre
Destory这个方法,我们用它的子类
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring-conflig.xml");
Beanlife bean=context.getBean("beanlife",Beanlife.class);
bean.say();
bean.preDestroy();
}
这里再强调一个问题:为什么属性注入要在初始化之前?这是因为如果一个类里面有依赖的对象的时候,我们在执行这个类的时候,需要先把这个对象给赋值。
例如如下代码:
@Component
public class UsePolice3 {
public Police police;
@Autowired
public UsePolice3(Police police)
{
this.police=police;
}
public void getpolice()
{
police.say();
}
}