Spring筆記二

xysympy發表於2020-10-30

通過構造器來建立bean物件

有name的建立

	<bean id="person1" class="com.yxm.entity.Person">
		<!-- 構造器有多少個需要傳入的值就傳多少個 -->
		<!-- public Person(String name, String gender,Integer age) -->
		<constructor-arg name="name" value="test01"></constructor-arg>
		<constructor-arg name="age" value="18"></constructor-arg>
		<constructor-arg name="gender" value="男"></constructor-arg>
	</bean>

沒有name的建立

可以沒有name,但是前提是必須和你要的構造器的引數一一對應,或者說你可以使用constructor-arg標籤的index屬性

<bean id="person2" class="com.yxm.entity.Person">
		<!-- 構造器有多少個需要傳入的值就傳多少個 -->
		<!-- public Person(String name, String gender,Integer age) -->
		<constructor-arg value="test01"></constructor-arg>
		<constructor-arg value="男" index="1"></constructor-arg>
		<constructor-arg value="18"></constructor-arg>
	</bean>

這個時候要是出現兩個過載的構造器,然後你又不想用name的話,那就用上constructor-arg標籤的type屬性來區分吧

<bean id="person3" class="com.yxm.entity.Person">
		<!-- 構造器有多少個需要傳入的值就傳多少個 -->
		<!-- public Person(String name, String gender) -->
		<!-- public Person(String name, Integer age) -->
		<constructor-arg value="test01"></constructor-arg>
		<constructor-arg value="男" type="java.lang.String"></constructor-arg>
</bean>

最好還是用name吧,看著都舒服

通過p名稱空間為bean屬性賦值

給我的感覺是,沒啥感覺,就是簡化了程式碼,如果屬性多了用這個賦值感覺很不美觀,但是可以作為了解
首先來引入p名稱空間
如果你是用sts外掛來建立的spring的配置檔案的話
在這裡插入圖片描述
點選,以後會出現如下介面
在這裡插入圖片描述
點選,然後會發現多了紅線這行程式碼(util那行程式碼是後面用到的)
在這裡插入圖片描述
如果不是的話,那麼就直接把紅線那部分程式碼複製到圖中位置
xmlns:p=“http://www.springframework.org/schema/p”
然後就是使用了

<!--這裡就是為age屬性賦值了-->
<bean id="person4" class="com.yxm.entity.Person" p:age="12"></bean>

正確為各種屬性賦值

使用null值

		<property name="name">
			<!-- 複雜型別的賦值 -->
			<null/>
		</property>

引用型別賦值(引用其他bean,使用內部bean)

引用其他bean

<!-- 被引用的bean物件 -->
	<bean id="car1" class="com.yxm.entity.Car">
		<property name="carName" value="路虎"></property>
		<property name="color" value="黑色"></property>
		<property name="price" value="3000000"></property>
	</bean>
<!-- 屬性ref的意思是引用,所以它和容器裡面取出來的car物件是一致的-->
<!--所以你變它變--!>
<property name="car" ref="car1"></property>
<!--或者<property name="car"><ref bean="car1"/> </property>--!>

使用內部bean(僅供內部使用,就算你對這個bean賦予id屬性還是沒什麼用)

<!-- 引用內部的bean物件,就是相當於建立一個new car物件然後賦值給屬性 -->
		<property name="car">
			<bean class="com.yxm.entity.Car">
				<property name="carName" value="路虎"></property>
				<property name="color" value="藍色"></property>
				<property name="price" value="3000000"></property>
			</bean>
		</property>

集合型別賦值(list,map,properties)

<!-- 測試集合型別的變數賦值 -->
<bean id="book1" class="com.yxm.entity.Book" p:bookName="東遊記"></bean>
<!-- 為list型別的變數賦值 -->
		<property name="books">
			<!-- 就相當於是list=new ArrayList<>() -->
			<list>
				<bean id="book1" class="com.yxm.entity.Book" p:bookName="西遊記"></bean>
				<ref bean="book1"/>
			</list>
		</property>
<!-- 為map型別的變數賦值 -->
		<property name="map">
			<!-- 相當於是為這個變數賦值map = new LinkedHashMap<>() -->
			<map>
				<!-- 表示一個鍵值對   注意我這邊使用的是Map<String,Object> -->
				<entry key="key01" value="普通"></entry>
				<entry key="key01" value="123"></entry>
				<entry key="key02" value-ref="book1"></entry>
				<entry key="key03">
					<bean class="com.yxm.entity.Car" p:carName="路虎"></bean>
				</entry>
				<!-- <entry key-ref="" value-type=""></entry> -->
				<!-- 當然entry裡面還是可以巢狀其他的複雜型別變數的 -->
			</map>
		</property>
<!-- 為Properties型別的變數賦值 -->
		<property name="properties">
			<!-- 相當於賦值new Properties()-->
			<props>
				<!-- 因為properties 的鍵值對都是String型別的,所以prop標籤沒有value屬性 -->
				<prop key="username">root</prop>
			</props>
		</property>

util名稱空間建立集合型別的bean

和p名稱空間匯入方式相同,選中util即可,若不是sts外掛則
xmlns:util=“http://www.springframework.org/schema/util”

<!-- util名稱空間建立集合型別的bean -->
	<!-- 就是能夠建立類似於bean的物件,當然這些物件是list map set等等 -->
	<!-- 這個也可以在內部使用,也就是意味著內部的也能夠在其他的bean中呼叫 -->
	<util:map id="map1" map-class="java.util.HashMap">
		<!-- 直接新增元素即可 -->
		<entry key="key01" value="普通"></entry>
		<entry key="key01" value="123"></entry>
		<entry key="key02" value-ref="book1"></entry>
		<entry key="key03">
			<bean class="com.yxm.entity.Car" p:carName="路虎"></bean>
		</entry>
	</util:map>
<!-- 測試util名稱空間 -->
<property name="map" ref="map1">
		</property>

級聯屬性(屬性的屬性)賦值

關鍵在於property這個標籤的name屬性上面

<!-- 級聯屬性(屬性的屬性)賦值 -->
	<bean id="person8" class="com.yxm.entity.Person">
		<property name="car" ref="car1"></property>
		<!-- 現在是修改賦值進行的值,比如修改車的價格 -->
		<!-- 需要注意的是這邊修改的話因為car是ref的緣故就會導致ref引用的那個物件也會發生改變 -->
		<property name="car.price" value="90000000"></property>
	</bean>

通過繼承實現bean配置資訊的重用和生成一個只能是配置檔案內部呼叫的bean物件,不能夠被getBean獲取

bean標籤的屬性parent,就是指定當前bean的配置資訊繼承於那個 和 bean標籤的屬性abstract="true

<!-- 通過bean標籤的parent進行實現,構造器也是可以的,而且下方這種person10有person9和person1的配置屬性 -->
	<!-- 可以有一個專門只供xml內部使用的bean物件,也就是在外面的getBean是獲得不到的,bean標籤的abstract屬性-->
	<bean id="person9" class="com.yxm.entity.Person" parent="person1" abstract="true">
		<property name="age" value="13"></property>
	</bean>
	<bean id="person10" class="com.yxm.entity.Person" parent="person9">
		<property name="gender" value="男"></property>
	</bean>

bean之間的依賴(單純的改變bean的建立的先後順序)

這個作為了解就好一般用不到,貌似--------bean標籤的depends-on="",裡面寫其他的beanid,多個的話用逗號隔開

<!-- bean標籤的depend-on屬效能夠決定在實現當前的bean物件的之前會先建立哪一個或者幾個bean物件 -->
<!--這個就表示當前的bean物件是在person9  person10 後生成--!>
	<!-- <bean depends-on="person9,person10"></bean> -->

bean的作用域

取決於bean標籤的scope屬性

<!-- 
		prototype:多例項,只有在你需要 它的時候容器才會進行建立並且每次建立出來的bean例項都是不同的
		singleton:單例項,是bean標籤的預設值,是在容器建立的時候已經生成的,並且獲取的時候都是已經建立好的那個
		request:在web環境下,同一次請求建立一個bean物件(一般不使用)
		session:在web環境下,同一次會話建立一個bean物件(一般不使用)
	 -->
	<bean id="car3" class="com.yxm.entity.Car"></bean>
	<bean id="car2" class="com.yxm.entity.Car" scope="prototype"></bean>
//測試多例項
		Car car01 = ac.getBean("car2",Car.class);
		Car car02 = ac.getBean("car2",Car.class);
		System.out.println(car01 == car02);
結果:false(單例項測試類似,返回true)

靜態,例項工廠方法建立bean

bean的預設建立就是框架利用反射new出來的bean例項
工廠模式:工廠幫我們建立物件,也就是有一個專門幫我們建立物件的類這個類就是工廠
靜態工廠:工廠本身不用建立物件,通過靜態方法呼叫,物件 = 工廠類.工廠方法名();
例項工廠:工廠本身需要建立物件,工廠類 工廠物件 = new工廠類();工廠物件.獲取物件的方法名();

靜態工廠的建立

首先建立一個靜態工廠類,裡面有獲取Car類的方法,然後再spring的配置檔案中進行相關配置

//Car類的靜態工廠
public class CarStaticFactory {

	public static Car getInstance(String carName) {
		Car car = new Car();
		car.setCarName(carName);
		car.setColor("藍色");
		car.setPrice(5000000);
		return car;
	}
}
//spring配置檔案
<!-- 靜態工廠建立需要的bean物件 factory-method就是獲取物件的方法-->
	<bean id="car4" class="com.yxm.factory.CarStaticFactory" factory-method="getInstance">
		<!-- 需要下面的標籤來傳遞引數 -->
		<!-- 因為只有一個引數,所以就不寫name了 -->
		<constructor-arg value="路虎"></constructor-arg>
	</bean>
然後呼叫getBean方法就行了

例項工廠的建立

先建立一個例項工廠的類物件,然後在spring配置檔案中進行相應的配置

//Car類的例項工廠
public class CarInstanceFactory {

	public Car getInstance(String carName) {
		Car car = new Car();
		car.setCarName(carName);
		car.setColor("藍色");
		car.setPrice(5000000);
		return car;
	}
}
//Spring配置檔案
<!-- 例項工廠建立需要的bean物件
			先建立例項工廠所對應的bean物件,然後就是類似於靜態工廠獲取的形式,只是多了一個屬性factory-bean
	 -->
	 <bean id="carFactory" class="com.yxm.factory.CarInstanceFactory"></bean>
	 <bean id="car5" class="com.yxm.entity.Car" factory-bean="carFactory" factory-method="getInstance">
	 	<!-- 傳入引數 -->
	 	<constructor-arg value="寶馬"></constructor-arg>
	 </bean>
呼叫getBean方法即可

FactoryBean來進行建立物件例項

可以理解為spring自帶的工廠介面
先建立一個工廠類實現這個介面,並且實現裡面的三個抽象方法,然後還是在spring的配置檔案中配置就好

public class MyFactoryBeanImpl implements FactoryBean<Car>{
	//如果配置檔案中建立的是這個bean例項會自動呼叫這個方法來獲取你所需要的物件例項
	@Override
	public Car getObject() throws Exception {
		// TODO 自動生成的方法存根
		System.out.println("MyFactoryBeanImpl.getObject()");
		Car car = new Car();
		car.setCarName("路虎");
		car.setColor("紅色");
		car.setPrice(5000000);
		return car;
	}

	//返回建立的例項物件的型別,Spring會自動進行呼叫來確定呼叫的是什麼型別
	@Override
	public Class<?> getObjectType() {
		// TODO 自動生成的方法存根
		System.out.println("MyFactoryBeanImpl.getObjectType()");
		return Car.class;
	}

	//是單例?
	@Override
	public boolean isSingleton() {
		// TODO 自動生成的方法存根
		System.out.println("MyFactoryBeanImpl.isSingleton()");
		return false;
	}

}
//spring配置檔案
<!-- factoryBean來進行建立物件例項 -->
	 <!-- factoryBean所建立的物件例項都是在你呼叫getBean的方法的時候才會去建立的,無論是單例項還是多例項
	 		也與介面所對應的方法中的是否為單例項的方法無關,這個方法只是能讓你獲取到的物件是單還是多
	  -->
	 <bean id="myFactoryBean" class="com.yxm.factory.MyFactoryBeanImpl"></bean>
然後呼叫getBean即可
這個方法一般都是在進行復雜型別的bean物件例項的時候會用到,比如那些和spring整合的時候,如SQLSessionFactory(知乎上看到的)
然後我有對這三個方法測試了一下
		Car car3 = ac.getBean("myFactoryBean",Car.class);
		Car car4 = ac.getBean("myFactoryBean",Car.class);
		System.out.println(car3 == car4);
結果
MyFactoryBeanImpl.isSingleton()
MyFactoryBeanImpl.isSingleton()
MyFactoryBeanImpl.getObject()
car建立
MyFactoryBeanImpl.isSingleton()
MyFactoryBeanImpl.getObject()
car建立
false
isSingleton這個方法測試過,你只要載入了那個配置檔案就會呼叫。
而getObject是在你呼叫getBean的時候呼叫。

FactoryBean的方法getObjectType()不知道是什麼時候呼叫的,很迷,就算我寫它返回不是getObject方法返回的值的型別還是未報錯。
若有知曉,煩請告知,不勝感激。
這是看完雷豐陽雷老師的ssm課程的筆記,感謝。

相關文章