一. Bean的生命周期
bean的生命周期可以表達為:bean的定義?bean的初始化?bean的使用?bean的銷毀
Bean的初始化過程
1)通過XML、Java annotation(注解)以及Java Configuration(配置類)
等方式加載Bean
2)BeanDefinitionReader:解析Bean的定義。在Spring容器啟動過程中,
會將Bean解析成Spring內部的BeanDefinition結構;
理解為:將spring.xml中的標簽轉換成BeanDefinition結構
有點類似于XML解析
3)BeanDefinition:包含了很多屬性和方法。例如:id、class(類名)、
scope、ref(依賴的bean)等等。其實就是將bean(例如)的定義信息
存儲到這個對應BeanDefinition相應的屬性中;將所有的bean標簽解析得到一個BeanDefinition定義對象,最終得到一個集合
4)BeanFactoryPostProcessor:是Spring容器功能的擴展接口。也就是在實例化之前給bean做一個拓展
注意:
1)BeanFactoryPostProcessor在spring容器加載完BeanDefinition之后,
在bean實例化之前執行的
2)對bean元數據(BeanDefinition)進行加工處理,也就是BeanDefinition
屬性填充、修改等操作
5)BeanFactory:bean工廠。它按照我們的要求生產我們需要的各種各樣的bean。BeanFactory會去解析處理整個集合,將所配置的所有JavaBean進行反射實例化
6)Aware感知接口:在實際開發中,經常需要用到Spring容器本身的功能資源
例如:BeanNameAware、ApplicationContextAware等等
BeanDefinition 實現了 BeanNameAware、ApplicationContextAware
7)BeanPostProcessor:后置處理器。在Bean對象實例化和引入注入完畢后,
在顯示調用初始化方法的前后添加自定義的邏輯。(類似于AOP的環繞通知)
二. Bean的單例與多例模式
在Spring中,bean可以被定義為兩種模式:prototype(多例)和singleton(單例)
singleton(單例):只有一個共享的實例存在,所有對這個bean的請求都會返回這個唯一的實例。單例的優點在于可以節約內存,弊端在于會有變量污染。
prototype(多例):對這個bean的每次請求都會創建一個新的bean實例,類似于new。多例的優劣則與單例相反,不會有變量污染,但卻非常消耗內存。
Spring bean默認是單例模式。
單例模式
代碼示例:
package com.xissl.beanLife;import java.util.List;public class ParamAction {private int age;private String name;private List<String> hobby;private int num = 1;public ParamAction() {super();}public ParamAction(int age, String name, List<String> hobby) {super();this.age = age;this.name = name;this.hobby = hobby;}public void execute() {System.out.println("this.num=" + this.num++);System.out.println(this.name);System.out.println(this.age);System.out.println(this.hobby);}
}
測試
package com.xissl.beanLife;import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;/** spring bean的生命週期* spring bean的單例多例*/
public class Demo2 {// 體現單例與多例的區別@Testpublic void test1() {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");// System.out.println(p1==p2);p1.execute();p2.execute();// 單例時,容器銷毀instanceFactory對象也銷毀;多例時,容器銷毀對象不一定銷毀;applicationContext.close();}}
spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- bean的生命周期--><bean id="paramAction" class="com.xissl.beanLife.ParamAction"><constructor-arg name="name" value="三豐"></constructor-arg><constructor-arg name="age" value="21"></constructor-arg><constructor-arg name="hobby"><list><value>抽煙</value><value>燙頭</value><value>大保健</value></list></constructor-arg></bean></beans>
運行結果:
這里的num值分別為1和2,則說明是單例的,單例模式即存在變量污染
在單例模式中,JavaBean是跟著spring上下文初始化的:
package com.xissl.beanLife;public class InstanceFactory {public void init() {System.out.println("初始化方法");}public void destroy() {System.out.println("銷毀方法");}public void service() {System.out.println("業務方法");}
}
測試
package com.xissl.beanLife;import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;/** spring bean的生命週期* spring bean的單例多例*/
public class Demo2 {// 體現單例與多例的初始化的時間點 instanceFactory@Testpublic void test2() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");}}
spring配置上下文:
<bean id="instanceFactory" class="com.xissl.beanLife.InstanceFactory"scope="singleton" init-method="init" destroy-method="destroy"></bean>
運行結果:
調用了初始化方法
多例模式
將spring配置文件中指定scope為prototype
<bean id="paramAction" class="com.xissl.beanLife.ParamAction" scope="prototype"><constructor-arg name="name" value="三豐"></constructor-arg><constructor-arg name="age" value="21"></constructor-arg><constructor-arg name="hobby"><list><value>抽煙</value><value>燙頭</value><value>大保健</value></list></constructor-arg></bean><bean id="instanceFactory" class="com.xissl.beanLife.InstanceFactory"scope="prototype" init-method="init" destroy-method="destroy"></bean>
運行結果:
在多例模式中,JavaBean是使用的時候才會創建,銷毀跟著jvm走:
運行結果:
沒有調用初始化方法