> 文章列表 > Bean对象的作用域和生命周期

Bean对象的作用域和生命周期

Bean对象的作用域和生命周期

文章目录:一.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初始化方法");}//表示具体使用Beanpublic void say() {System.out.println("执行say方法");}@PostConstruct  //构造方法public void myinit() {System.out.println("执行了注解初始化方法");}@PreDestroy     //摧毁beanpublic 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;@Autowiredpublic UsePolice3(Police police){this.police=police;}public void getpolice(){police.say();}}