Spring核心容器的詳細解析以及IOC和DI和過程全解

1.spring的簡介

spring是一個一站式的解決框架,旨在解決企業開發中各個層級之間的問題.
所謂一站式的解決方案:就是spring可以支持我們各個層級包括數據展示層,業務層和持久層都有對應的解決方案.
Spring的出現是爲了取代 EJB(Enterprise JavaBean)開發模式的臃腫,低效,脫離現實

2.spring優點

方便解耦,簡化開發
AOP編程的支持
申明式事務的支持
方便程序的測試等等

3.spring的架構體系


其他地方扒的,這次只聊Core Container(核心容器)

4.Core Container(核心容器)

容器用來裝javaBean.
spring容器通過單例設計模式+工廠設計模式+反射的機制來加載獲取類對象
java中單例設計模式定義:"一個類有且僅有一個實例,並且自行實例化向整個系統提供"
spring 核心容器core, context,beans, SpEL
context容器:提供了ApplicationContext容器,加載配置文件(獲取唯一Id標識)  context.getBeans獲取bean對象,加載完成對象
ApplicationContext.xml中配置Bean
	<bean id="userInterfaceImpl" class="com.youlin.spring.demo1.UserInterfaceImpl">
		<property name="username" value="張三"></property>
	</bean>
測試類中進行獲取
	@Test
	public void getUser() throws Exception {
		//獲取容器
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserInterface bean = (UserInterface) context.getBean("userInterfaceImpl");
		bean.sayHello();
	}
spring爲某個屬性賦值
bean內進行配置屬性property  name  value  底層調用的是set get方法
普通的爲對象賦值有兩種get set  和構造器
spring也是兩種方法
ApplicationContext是一個接口  它的最大接口是BeanFactory
Struts2  採用的對象是多例的.

5.spring的第一大特性IOC

Inversion Of Controller  控制反轉
把創建對象的權利反轉交給了spring,這一過程就叫做控制反轉
在spring中加載對象,就是通過反射加載
講個笑話:
什麼是IOC? 就是通過反射加載對象的過程
什麼是反射?  mysql的驅動連接就是通過反射來加載的.

1.容器創建的三種方式

第一種方式使用了ClassPathXmlApplicationContext子類對象
	/**
	 * 容器創建的第一種方式,也是最常用的一種方式
	 * 使用配置文件的相對路徑
	 * spring 入門案例
	 * @throws Exception
	 */
	@Test
	public void getUser() throws Exception {
		//獲取容器
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserInterface bean = (UserInterface) context.getBean("userInterfaceImpl");
		bean.sayHello();
	}
容器創建的第二種方式
使用了FileSystemXmlApplicationContext子類對象
	/**
	 * 容器創建的第二種方式
	 * 使用配置文件的路徑是絕對路徑
	 */
	@Test
	public void getFileSystemContainer() throws Exception {
		ApplicationContext context = new FileSystemXmlApplicationContext("D:\\workspace01\\springDay01\\src\\main\\resources\\ApplicationContext.xml");
		UserInterface bean = (UserInterface) context.getBean("userInterfaceImpl");
		bean.sayHello();
	}
第三種方式:
	/**
	 * 容器創建的第三種方式,已經過時了,不在使用
	 * 它是一種懶加載形式
	 * bean已經定義了,不用到的時候是不加載的,使用的時候纔會加載
	 * 上面兩種只管創建,不管你用不用
	 * @throws Exception
	 */
	@Test
	public void getXmlContainer() throws Exception {
		Resource resource = new ClassPathResource("ApplicationContext.xml");
		XmlBeanFactory beanFactory = new XmlBeanFactory(resource );
		UserInterface bean = (UserInterface) beanFactory.getBean("userInterfaceImpl");
		bean.sayHello();
	}

2.加載對象的三種方式

第一種方式:
默認構造器
上述例子
第二種方式:使用靜態工廠來創建對象
創建靜態工廠類
package com.youlin.spring.demo2;

public class UserBean2Factory {
	public static UserBean2 getUserBean2() {
		return new UserBean2();
	}
}
配置
<!-- 通過靜態工廠來創建對象 -->
<bean id="userBean2Factory" class="com.youlin.spring.demo2.UserBean2Factory" factory-method="getUserBean2"></bean>
獲取
	/**
	 * 第二種創建對象的方式:通過靜態工廠來創建對象
	 */
	@Test
	public void getUserBean2() throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserBean2 bean = (UserBean2) context.getBean("userBean2Factory");
		bean.userBean2SayHello();
	}
第三種方式
通過實例工廠來創建對象,比較複雜,主要目的是可以在實例工廠初始化對象之前加塞一些自己的其他邏輯操作.
創建實例工廠
package com.youlin.spring.demo2;

public class UserBean3Factory {
	
	public UserBean3 getUserBean3() {
		return new UserBean3();
	}

}
配置
	<!-- 通過實例工廠來創建對象 -->
	<bean id="userBean3Factory" class="com.youlin.spring.demo2.UserBean3Factory"></bean>
	<bean id="userBean3" class="com.youlin.spring.demo2.UserBean3" factory-bean="userBean3Factory" factory-method="getUserBean3"></bean>
	
獲取
	/**
	 * 第三種創建對象的方式,通過實例工廠來創建對象
	 * 可以在創建對象之前,加塞一些自己其他的邏輯,在實例工廠內加塞
	 * @throws Exception
	 */
	@Test
	public void getUserBean3() throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		UserBean3 bean = (UserBean3) context.getBean("userBean3");
		bean.sayHello();
	}

3.bean的作用域及作用範圍以及生命週期

bean的屬性作用域scope:
	<!-- bean的作用域與作用範圍 -->
	<bean id="orders" class="com.youlin.spring.demo3.Orders" scope="singleton" init-method="initMethod" destroy-method="destroyMethod"></bean>
	/**
	 * 作用域與作用範圍
	 * @throws Exception
	 */
	@Test
	public void getOrders() throws Exception {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		Orders bean = (Orders) context.getBean("orders");
		Orders bean2 = (Orders) context.getBean("orders");
		System.out.println(bean.toString());
		System.out.println(bean2.toString());
		context.close();
	}
默認爲單例模式.

prototype : 多例
request : 創建對象並且丟到request作用域中去,一般不使用
session : 創建對象並且放到session作用域中去,一般不使用
singleton: 單例
生命週期: 初始化和銷燬
初始化:init-method=""
創建的時候調用
銷燬的方法: destroy-method=""
在容器關閉的時候被調用
初始化和銷燬的方法都是我們自定義的
注:
ApplicationContext是一個接口沒有close()方法
在其實現類ClassPathXmlApplicationContext中才會有close()方法
容器的關閉在spring與web整合的時候會提到
容器一般是不會關閉的,頻繁的打開和關閉容器也是一種開銷.
總結IOC控制反轉
將創建對象的權利交給spring來完成
spring通過反射來加載對象
首先配置bean容器,然後再加載bean容器,由bean容器加載對象初始化對象.

6.Spring的第二大特性 DI   Dependency Injection  依賴注入

把我們對對象屬性賦值的過程交給spring
就是spring給對象屬性賦值的一個過程
普通屬性賦值兩種,構造器,get,set兩種
DI也是這兩種
先有IOC,再有DI,即先有創建對象,再有屬性賦值
賦值對象屬性通過ref來進行引用日期Date也需要
bean沒有配置id,也可以獲取對象,通過.class反射的方法來獲得對象
賦值方式
通過構造器來爲屬性賦值
	<!-- 通過構造器來爲屬性賦值 -->
	<bean id="jerry" class="com.youlin.spring.demo4.Jerry">
		<!-- 通過constructor-arg來爲我們的屬性賦值
			name 指定哪個屬性的名稱
		 -->
		<constructor-arg name="name" value="jerry"></constructor-arg>
		<constructor-arg name="sex" value="1"></constructor-arg>
		<constructor-arg name="color" value="brown"></constructor-arg>
	</bean>
通過索引賦值
	<!-- 通過索引來爲屬性賦值 -->
	<bean id="jerry" class="com.youlin.spring.demo4.Jerry">
		<constructor-arg index="0" value="jerry2"></constructor-arg>
		<constructor-arg index="1" value="0"></constructor-arg>
		<constructor-arg index="2" value="黑白色"></constructor-arg>
	</bean>
通過P名稱空間和C名稱空間賦值
p名稱空間是property的簡寫
C名稱空間是constructor-arg簡寫
zhuyaoshi簡化屬性賦值的操作
	<!-- 通過P名稱空間來爲屬性賦值 -->
	<bean id="tom" class="com.youlin.spring.demo4.Tom" p:age="10" p:tomName="tom" ></bean>
	
	<!-- 通過C名稱空間來爲構造器的屬性注入 -->
	<bean id="jerry4" class="com.youlin.spring.demo4.Jerry" c:color="白色" c:sex="0" c:name="jerry4" ></bean>
	
SpEL表達式
類似於jstl與el表達式可以支持我們在爲屬性賦值的時候,通過spel表達式來進行更改我們的屬性
#{ }
	<!-- spel表達式 -->
	<bean id="user2" class="com.youlin.spring.demo4.User">
		<property name="age" value="10"></property>
		<property name="username" value="tom"></property>
	</bean>
	<bean id="tom2" class="com.youlin.spring.demo4.Tom">
		<property name="tomAge" value="#{user2.getAge()+20}"></property>
		<property name="tomName" value="#{user2.getUsername()+'tomtom'}"></property>
		<property name="jerry" value="#{jerry4}"></property>
	</bean>

未完待續......
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章