1. 程式人生 > 實用技巧 >Spring基礎知識彙總

Spring基礎知識彙總

一、Spring概述

  • ①Spring是一個開源框架

  • ②Spring為簡化企業級開發而生,使用Spring開發可以將Bean物件,Dao元件物件,Service元件物件等交給Spring容器來管理,這樣使得很多複雜的程式碼在Spring中開發卻變得非常的優雅和簡潔,有效的降低程式碼的耦合度,極大的方便專案的後期維護、升級和擴充套件。

  • ③Spring是一個IOC(DI)和AOP容器框架。

  • ④Spring的優良特性

    • [1]非侵入式:基於Spring開發的應用中的物件可以不依賴於Spring的API
    • [2]控制反轉:IOC——Inversion of Control,指的是將物件的建立權交給Spring去建立。使用Spring之前,物件的建立都是由我們自己在程式碼中new建立。而使用Spring之後。物件的建立都是由給了Spring框架。
    • [3]依賴注入:DI——Dependency Injection,是指依賴的物件不需要手動呼叫setXX方法去設定,而是通過配置賦值。
    • [4]面向切面程式設計:Aspect Oriented Programming——AOP
    • [5]容器:Spring是一個容器,因為它包含並且管理應用物件的生命週期
    • [6]元件化:Spring實現了使用簡單的元件配置組合成一個複雜的應用。在 Spring 中可以使用XML和Java註解組合這些物件。
    • [7]一站式:在IOC和AOP的基礎上可以整合各種企業應用的開源框架和優秀的第三方類庫(實際上Spring 自身也提供了表述層的SpringMVC和持久層的Spring JDBC)。

1.1、Spring模組介紹

  • Spring框架分為四大模組

    • core核心模組。負責管理元件的Bean物件

      • spring-beans-4.0.0.RELEASE.jar
      • spring-context-4.0.0.RELEASE.jar
      • spring-core-4.0.0.RELEASE.jar
      • spring-expression-4.0.0.RELEASE.jar
    • 面向切面程式設計

      • spring-aop-4.0.0.RELEASE.jar
      • spring-aspects-4.0.0.RELEASE.jar
    • 資料庫操作

      • spring-jdbc-4.0.0.RELEASE.jar
      • spring-orm-4.0.0.RELEASE.jar
      • spring-oxm-4.0.0.RELEASE.jar
      • spring-tx-4.0.0.RELEASE.jar
      • spring-jms-4.0.0.RELEASE.jar
    • Web模組

      • spring-web-4.0.0.RELEASE.jar
      • spring-webmvc-4.0.0.RELEASE.jar
      • spring-websocket-4.0.0.RELEASE.jar
      • spring-webmvc-portlet-4.0.0.RELEASE.jar

二、SpringIOC

  • IOC 全稱指的是 Inverse Of Control 控制反轉。

  • 控制反轉指的是 物件的 建立 控制權的反轉。

  • 在我們使用Spring之前。我們的物件建立都是由我們自己手動new出來一個物件比如:

    • BookDao bookDao = new BookDaoImpl(); 自己手動的去建立。
  • 而使用了Spring之後。物件的建立是交給Spring容器來負責。這就是控制反轉。

  • 什麼是DI

    • DI 指的是Dependency Injection 。是依賴注入的意思。

    • 什麼是依賴注入。舉個例子。

      • 在前面我們使用BookService處理業務的時候,都需要依賴BookDao去執行資料庫的操作。而這個依賴的BookDao物件,是由自己程式碼new建立並賦值的。

      • public class BookServiceImpl implements BookService {
            private BookDao bookDao = new BookDaoImpl();
        }
        // 而在Spring中,我們只需要定義BookDao物件即可。然後把物件的賦值過程交給Spring來實現。
        public class BookServiceImpl implements BookService {
        
            private BookDao bookDao;
        
            public void setBookDao(BookDao bookDao) {
                this.bookDao = bookDao;
            }
        }
        

2.1、環境準備

2.2.1、引入Jar包

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.1.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

2.2.2、引入日誌

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

2.2.3、單元測試

package demo.spring;

import demo.spring.pojo.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloIOC {

    @Test
    public void test1() {
        // * 1. 引入Jar包
        // * 2. 配置application核心配置
        // * 3. 獲取 ApplicationContext 物件
        // * 4. 通過 ApplicationContext 獲取 bean物件
        // applicationContext 就是 IOC容器
        // ClassPathXmlApplicationContext是容器的實現類
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 從容器中獲取 id 為 person 定義的物件
        Person person = (Person) applicationContext.getBean("person");
        System.out.println(person);
    }
}

2.2.4、注意事項

  • 1、FileSystemXmlApplicationContext怎麼用?

    • 答:new FileSystemXmlApplicationContext("src/applicationContext.xml");
  • 2、Bean是在什麼時候被建立的?

  • 答:Bean在new ClassPathXmlApplicationContext的時候會被建立。

  • 3、如果呼叫getBean多次,會建立幾個?

    • 答:預設情況下,多次呼叫,也只會返回同一個物件例項。
  • 4、如果在getBean的時候,傳入的id不存在,就會報以下錯誤:

    • 答: No bean named 'person01' is defined

2.2、IOC依賴注入

2.2.1、IOC通過ID獲取物件

<?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標籤配置一個元件類======會由Spring容器來管理
			id 屬性給bean新增唯一標識
			class 屬性設定 配置的類的全類名
	 -->
	<bean id="person" class="demo.spring.pojo.Person">
		<!-- property 標籤 設定 屬性資訊 -->
		<property name="id" value="1" />
		<property name="name" value="張三" />
		<property name="age" value="18" />
		<property name="phone" value="18688888888" />
	</bean>
</beans>
-----------------------------------------------------------------------------------
	@Test
	public void test1() {
		// applicationContext 就是 IOC容器
		// ClassPathXmlApplicationContext是容器的實現類
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		// 從容器中獲取 id 為 person 定義的物件
		Person person = (Person) applicationContext.getBean("person");
		System.out.println( person );
	}

2.2.2、通過型別獲取物件

  • 當applicationContext.xml配置檔案中,只有一個Person.class的物件例項配置的時候,程式是可以正常執行的。

  • 常見錯誤

    • 當在applicationContext.xml配置檔案中。有多個同Person.class型別實現的時候。
    • No qualifying bean of type [demo.spring.pojo.Person] is defined;expected single matching bean but found2;person,person02
<?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標籤配置一個元件類======會由Spring容器來管理
			id 屬性給bean新增唯一標識
			class 屬性設定 配置的類的全類名
	 -->
	<bean id="person" class="demo.spring.pojo.Person">
		<!-- property 標籤 設定 屬性資訊 -->
		<property name="id" value="1" />
		<property name="name" value="張三" />
		<property name="age" value="18" />
		<property name="phone" value="18688888888" />
	</bean>
	<bean id="person02" class="com.atguigu.pojo.Person">
		<!-- property 標籤 設定 屬性資訊 -->
		<property name="id" value="2" />
		<property name="name" value="李四" />
	</bean>
</beans>
------------------------------------------------------------------------
	@Test
	public void test2() {
		// applicationContext 就是 IOC容器
		// ClassPathXmlApplicationContext是容器的實現類
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		// 從容器中獲取 id 為 person 定義的物件
		Person person = (Person) applicationContext.getBean(Person.class);
		System.out.println( person );
	}

2.2.3、通過構造方法引數名注入值

	<!-- int id, String name, int age, String phone -->
	<bean id="person03" class="demo.spring.pojo.Person">
		<!-- constructor-arg 表示有參構造方法中的一個引數 -->
		<constructor-arg name="id" value="3"></constructor-arg>
		<constructor-arg name="name" value="王五"></constructor-arg>
		<constructor-arg name="age" value="18"></constructor-arg>
		<constructor-arg name="phone" value="13666666666"></constructor-arg>
	</bean>	
	------------------------------------------
	@Test
	public void test3() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person03 = (Person) applicationContext.getBean("person03");
		System.out.println(person03);
	}

2.2.4、 index屬性指定引數的位置

	<!-- int id, String name, int age, String phone -->
	<bean id="person04" class="demo.spring.pojo.Person">
		<!-- index 表示引數的索引位置。索引值從零0開始算 -->
		<constructor-arg index="0" value="4"></constructor-arg>
		<constructor-arg index="1" value="王五"></constructor-arg>
		<constructor-arg index="3" value="18610101010"></constructor-arg>
		<constructor-arg index="2" value="18"></constructor-arg>
	</bean>
	-----------------------------------------------------------
	@Test
	public void test4() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person04 = (Person) applicationContext.getBean("person04");
		System.out.println(person04);
	}

2.2.5、根據引數型別注入

	<!-- int id, String name, int age, String phone -->
	<bean id="person05" class="demo.spring.pojo.Person">
		<!-- index 表示引數的索引位置。索引值從零0開始算 -->
		<constructor-arg index="3" value="18610101010" type="java.lang.String"></constructor-arg>
		<constructor-arg index="1" value="王五" type="java.lang.String"></constructor-arg>
		<!-- 
           使用型別區分過載的建構函式
			這個地方有一點需要特別注意:
				如果程式碼中的型別是Integer , 那麼type型別是 java.lang.Integer
				如果程式碼中的型別是int , 那麼type型別是int
		 -->
		<constructor-arg index="2" value="18" type="int"></constructor-arg>
		<constructor-arg index="0" value="4" type="int"></constructor-arg>
	</bean>
	--------------------------------------------
	@Test
	public void test5() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person05 = (Person) applicationContext.getBean("person05");
		System.out.println(person05);
	}

2.2.6、IOC之P名稱空間

<!-- p名稱空間,使用很簡單。 p:屬性="值" -->
<bean id="person06" class="demo.spring.pojo.Person" p:id="6" p:name="第6個人" p:age="18" p:phone="18600001111" />
------------------------------
	@Test
	public void test6() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person06 = (Person) applicationContext.getBean("person06");
		System.out.println(person06);
	}

2.2.7、測試null值的使用

修改Person類的屬性,新增預設值
public class Person {
	private int id;
	private String name;
	private int age;
	private String phone = "預設值";
}

	<bean id="person07" class="demo.spring.pojo.Person" p:id="7" p:age="18" p:name="第七個人">
		<property name="phone">
			<null />
		</property>
    </bean>
    
    @Test
	public void test7() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person07 = (Person) applicationContext.getBean("person07");
		System.out.println(person07);
	}

2.2.8、IOC之子物件的賦值測試

public class Car {
	private String name;
	private String carNo;

public class Person {
	private int id;
	private String name;
	private int age;
	private String phone;
	private Car car;
-------------------------------------------------	
	<!-- 定義一個車 -->
	<bean id="car" class="demo.spring.pojo.Car" p:name="寶馬" p:carNo="京A12312" />
	<!--定義一個Person類 -->
	<bean id="person10" class="demo.spring.pojo.Person">
		<property name="id" value="10" />
		<property name="name" value="perosn10" />
		<property name="age" value="18" />
		<property name="phone" value="0101001" />
		<!-- ref 表示引用一個物件 -->
		<property name="car" ref="car" />
	</bean>
-------------------------------------------------	
	@Test
	public void test10() {
		//建立容器物件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person10 = (Person) applicationContext.getBean("person10");
		System.out.println(person10);
	}
	

2.2.9、IOC之內部Bean的使用

  • 內部的Bean不能被外部使用
	<bean id="person11" class="demo.spring.pojo.Person">
		<property name="id" value="10" />
		<property name="name" value="perosn10" />
		<property name="age" value="18" />
		<property name="phone" value="0101001" />
		<!-- ref 表示引用一個物件 -->
		<property name="car">
			<bean id="car02" class="demo.spring.pojo.Car" p:name="保時捷" p:carNo="京B12341"></bean>
		</property>
	</bean>
	--------------------------------------
		public void test11() {
            //建立容器物件
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person11 = (Person) applicationContext.getBean("person11");
            System.out.println(person11);
            System.out.println( applicationContext.getBean("car02") );			// 內部的Bean不能被外部使用
		}

2.2.10、IOC之List屬性的賦值

public class Person {
	private int id;
	private String name;
	private int age;
	private String phone;
	private Car car;
	private List<String> phones;
-----------------------------------------	
<bean id="person12" class="demo.spring.pojo.Car">
		<property name="id" value="10" />
		<property name="name" value="perosn10" />
		<property name="age" value="18" />
		<property name="phone" value="0101001" />
		<!-- ref 表示引用一個物件 -->
		<property name="car">
			<bean id="car02" class="demo.spring.pojo.Car" p:name="保時捷"
				p:carNo="京B12341"></bean>
		</property>
		<!-- 給list集合賦值 -->
		<property name="phones">
			<list>
				<value>18611110000</value>
				<value>18611110001</value>
				<value>18611110002</value>
			</list>
		</property>
	</bean>
---------------------------------------  
	@Test
	public void test12() {
		//建立容器物件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person12 = (Person) applicationContext.getBean("person12");
		System.out.println(person12);
	}	

2.2.11、IOC之Map屬性的賦值

public class Person {
	private int id;
	private String name;
	private int age;
	private String phone;
	private Car car;
	private List<String> phones;
	private Map<String, Object> map;
	
<bean id="person13" class="demo.spring.pojo.Person">
		<property name="id" value="10" />
		<property name="name" value="perosn10" />
		<property name="age" value="18" />
		<property name="phone" value="0101001" />
		<!-- ref 表示引用一個物件 -->
		<property name="car">
			<bean id="car02" class="demo.spring.pojo.Car" p:name="保時捷"
				p:carNo="京B12341"></bean>
		</property>
		<!-- map物件 -->
		<property name="map">
			<map>
				<!-- entry 表示map中有每一項 -->
				<entry key="aaa" value="aaaValue" />
				<entry key="bbb" value="bbbValue" />
				<entry key="ccc" value="cccValue" />
			</map>
		</property>
	</bean>	
	
	
	@Test
	public void test13() {
		//建立容器物件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person13 = (Person) applicationContext.getBean("person13");
		System.out.println(person13);
	}
	

2.2.12、IOC之Properties屬性的賦值

public class Person {
	private int id;
	private String name;
	private int age;
	private String phone;
	private Car car;
	private List<String> phones;
	private Map<String, Object> map;
	private Properties props;
	--------------------------------------------
	<bean id="person14" class="com.atguigu.pojo.Person">
		<property name="id" value="10" />
		<property name="name" value="perosn10" />
		<property name="age" value="18" />
		<property name="phone" value="0101001" />
		<!-- map物件 -->
		<property name="props">
			<props>
				<prop key="username">root</prop>
				<prop key="password">root</prop>
				<prop key="drivers">com.mysql.jdbc.Driver</prop>
				<prop key="url">jdbc:mysql://localhost:3306/spring</prop>
			</props>
		</property>
    </bean>	
   	--------------------------------------------
   	@Test
	public void test14() {
		//建立容器物件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person14 = (Person) applicationContext.getBean("person14");
		System.out.println(person14);
	}

2.2.13、IOC之util 名稱空間

	<!-- 定義一個list集合 -->
	<util:list id="list1">
		<value>string1</value>
		<value>string2</value>
		<value>string3</value>
	</util:list>

	<bean id="person15" class="com.atguigu.pojo.Person">
		<property name="id" value="10" />
		<property name="name" value="perosn10" />
		<property name="age" value="18" />
		<property name="phone" value="0101001" />
		<!-- list物件 ref表示引用 -->
		<property name="phones" ref="list1" />
	</bean>
	
	@Test
	public void test15() {
		//建立容器物件
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person15 = (Person) applicationContext.getBean("person15");
		System.out.println(person15);
		
		List<String> list = (List<String>) applicationContext.getBean("list1");
		System.out.println(list);
	}	
	

2.2.14、IOC之級聯屬性賦值

	<bean id="person16" class="com.atguigu.pojo.Person">
		<property name="id" value="10" />
		<property name="name" value="perosn10" />
		<property name="age" value="18" />
		<property name="phone" value="0101001" />
		<!-- list物件 ref表示引用 -->
		<property name="car"  ref="car"/>
		<!-- 級聯屬性 -->
		<property name="car.name" value="我的愛車"  />
	</bean>
--------------------------------
	@Test
	public void test16() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person16 = (Person) applicationContext.getBean("person16");
		System.out.println( person16 );
	}

2.2.15、IOC之靜態工廠方法建立Bean

public class PersonFactory {
	public static Person createPerson() {
		Person person = new Person();
		person.setId(17);
		person.setName("這是靜態工廠方法");
		return person;
	}
}
--------------------------------
<!-- 使用靜態工廠方法
		class 是工廠 的全類名
		factory-method 這是工廠方法
	 -->	
<bean id="person17" class="com.atguigu.pojo.factory.PersonFactory" factory-method="createPerson" />
--------------------------------
	@Test
	public void test17() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person16 = (Person) applicationContext.getBean("person17");
		System.out.println( person16 );
	}

2.2.16、IOC之工廠例項方法建立Bean

public class PersonFactory {
	public Person getPerson() {
		Person person = new Person();
		person.setId(18);
		person.setName("這是工廠例項方法");
		return person;
	}
}
--------------------------
	<!-- 工廠例項方法分兩步:
		第一步:先使用bean標籤配置一個bean物件
		第二步:使用bean標籤配置factory-bean和factory-method方法
	 -->
	<bean id="personFactory" class="com.atguigu.pojo.factory.PersonFactory" />
	<!-- 
		factory-bean表示使用哪一個工廠物件的實現
		factory-method表示呼叫物件的哪一個方法去獲取物件例項
	 -->
	<bean id="person18" factory-bean="personFactory" factory-method="getPerson">
	--------------------------
	@Test
	public void test18() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person18 = (Person) applicationContext.getBean("person18");
		System.out.println( person18 );
	}	
	

2.2.17、IOC之FactoryBean介面方式

public class PersonFactoryBean implements FactoryBean<Person> {

	public Person getObject() throws Exception {
		Person person = new Person();
		person.setId(20);
		person.setName("這是PersonFactoryBean創建出來的");
		return person;
	}

	public Class<?> getObjectType() {
		return Person.class;
	}

	/**
	 * 判斷是否是單例<br/>
	 * 		返回true是單例 <br/>
	 *  	返回false是多例
	 */
	public boolean isSingleton() {
		return true;
	}
}
----------------
	<!-- 使用FactoryBean介面方式建立Bean物件 -->
	<bean id="person19" class="com.atguigu.pojo.factory.PersonFactoryBean" />
	----------------
		@Test
	public void test19() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
				"applicationContext.xml");
		Person person19 = (Person) applicationContext.getBean("person19");
		System.out.println(person19);

		Person person191 = (Person) applicationContext.getBean("person19");
		System.out.println(person19 == person191); // true
	}

2.2.18、IOC之繼承Bean配置

	<!-- 先定義一個base的 person物件 -->
	<bean id="base" class="com.atguigu.pojo.Person" p:name="basePerson" p:age="18" p:id="12312"/>
	<!-- 然後在另一個bean中。使用parent繼承所有的 -->
	<bean id="person20" class="com.atguigu.pojo.Person" parent="base" p:id="20" />
	
	@Test
	public void test20() {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person20 = (Person) applicationContext.getBean("person20");
		System.out.println(person20);
		
		System.out.println( "這是base的---" + applicationContext.getBean("base") );
	}

2.2.19、IOC之元件建立順序

public class A {
	public A() {
		System.out.println("A 被建立了");
	}
}
public class B {
	public B() {
		System.out.println("B 被建立了");
	}
}
public class C {
	public C() {
		System.out.println("C 被建立了");
	}
}
----------------------
<!-- 預設情況下。bean物件建立的順序,是從上到下
			depends-on 可以設定依賴
	 -->
	<bean id="a" class="com.atguigu.pojo.A" depends-on="b,c"/>
	<bean id="b" class="com.atguigu.pojo.B" />
	<bean id="c" class="com.atguigu.pojo.C" />
----------------------------
	@Test
	public void test1() throws Exception {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	}

2.2.20、基於xml配置檔案的自動注入

public class Car {
	private String carNo;
	private String name;

public class Person {

	private Car car;
	public Person(Car car) {
		this.car = car;
	}
-----------
	<bean id="car1" class="com.atguigu.pojo.Car">
		<property name="carNo" value="京B23412" />
		<property name="name" value="勞死來死"/>
	</bean>
	<bean id="car2" class="com.atguigu.pojo.Car">
		<property name="carNo" value="京B23412" />
		<property name="name" value="勞死來死2"/>
	</bean>
	<!-- 
		autowire 屬性設定是否自動查詢bean物件並給子物件賦值
		
		default 和 no 表示不自動查詢並注入(你不賦值,它就null)
		byName 	是指通過屬性名做為id來查詢bean物件,並注入
					1、找到就注入
					2、找不到就為null
		byType  是指按屬性的型別進行查詢並注入
					1、找到一個就注入
					2、找到多個就報錯
					3、沒有找到就為null
		constructor 是指按構造器引數進行查詢並注入。
					1、先按照構造器引數型別進行查詢並注入
					2、如果按型別查詢到多個,接著按引數名做為id繼續查詢並注入。
					3、按id查詢不到,就不賦值。
	 -->
	<bean id="p19" class="com.atguigu.pojo.Person" autowire="constructor">
		<property name="name" value="p19" />
	</bean>
	

2.2.21、IOC之Bean的單例和多例(重點)

	<!-- 
		scope 屬性設定物件的域
			singleton			表示單例(預設)
								1、Spring容器在建立的時候,就會建立Bean物件
								2、每次呼叫getBean都返回spring容器中的唯一一個物件
								
			prototype			表示多例
								1、多例在Spring容器被建立的時候,不會跟著一起被建立。
								2、每次呼叫getBean都會建立一個新物件返回
								
			request				在一次請求中,多次呼叫getBean方法都是返回同一個例項。
								getBean("p20"); 底層大概的實現原理
								Object bean = request.getAttribute("p20");
								if (bean == null) {
									bean = new 物件();
									request.setAttribute("p20",bean);
								}
								return bean;
								
								
			session				在一個會話中,多次呼叫getBean方法都是返回同一個例項。
								getBean("p20"); 底層大概的實現原理
								Object bean = session.getAttribute("p20");
								if (bean == null) {
									bean = new 物件();
									session.setAttribute("p20",bean);
								}
								return bean;
	 -->
	<bean id="p20" class="com.atguigu.pojo.Person" scope="singleton">
		<property name="name" value="p20" />
	</bean>
	----------------------
	@Test
	public void test3() throws Exception {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		System.out.println( applicationContext.getBean("p20") );
		System.out.println( applicationContext.getBean("p20") );
		System.out.println( applicationContext.getBean("p20") );
		System.out.println( applicationContext.getBean("p20") );			// 單例模式得出都一樣
	}
	

2.3、IOC生命週期

	<!-- 
		init-method配置初始化方法(bean物件建立之後)
		destroy-method配置銷燬方法(在spring容器關閉的時候,只對單例有效)
	 -->
	<bean id="p21" class="com.atguigu.pojo.Person" init-method="init" destroy-method="destroy" scope="singleton">
		<property name="name" value="p21"/>
	</bean>
	------------------------------
	@Test
	public void test4() throws Exception {
		ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		applicationContext.getBean("p21");
		applicationContext.close();
	}

單例的bean,生命週期有11個步驟:

  • 1.instantiate bean物件例項化,bean物件例項化,是在載入配置檔案的時候例項的。即,我們啟動spring容器的時候,載入配置檔案,此時就例項化bean了。
  • 2.populate properties 封裝屬性
  • 3.如果Bean實現BeanNameAware, 執行 setBeanName
  • 4.如果Bean實現BeanFactoryAware 或者 ApplicationContextAware,設定工廠 setBeanFactory 或者上下文物件 setApplicationContext
  • 5.如果存在類實現 BeanPostProcessor(後處理Bean) ,執行postProcessBeforeInitialization(此點常常用來增強bean)
  • 6.如果Bean實現InitializingBean 執行 afterPropertiesSet
  • 7.呼叫 指定初始化方法 init
  • 8.如果存在類實現 BeanPostProcessor(後處理Bean) ,執行postProcessAfterInitialization(此點常常用來增強bean)
  • 9.執行業務處理
  • 10.如果Bean實現 DisposableBean 執行 destroy
  • 11.呼叫 指定銷燬方法

`