本章補充bean的做用域和自動裝配java
以前提到能夠用scope來設置單例模式web
<bean id="type" class="cn.dota2.tpye.Type" scope="singleton"></bean>
除此以外還有幾種用法
singleton:單例模式,Spring默認使用單例模式,也是開發中最經常使用的類型。即:加載bean配置文件只能生成類的一個實例,只會new一次。
prototype:多例模式,用到一次就會new一次。由於對象多,因此不會銷燬。
request:應用在web項目中,Spring建立這個類以後,將這個類存到request範圍內。
session:應用在web項目中,Spring建立這個類以後,將這個類存到session範圍內。
globalsession:應用在web項目中,必須在portlet環境下才能使用。即在系統下存入數據後,在其子系統下就不須要從新登陸。
注意默認狀況下bean的做用域是單例。以前我有個疑問,既然是單列,爲何能夠在java代碼中建立兩個實例對象?以下圖spring
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); Student student=(Student)ac.getBean("student"); Student student1=(Student)ac.getBean("student");
其實這裏的getBean獲取的bean都是一個bean。咱們改student的名字,student1的名字也會改變。由於student在容器裏只有一個。session
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); Student student=(Student)ac.getBean("student"); Student student1=(Student)ac.getBean("student"); student.show(); student.setName("王五"); student1.show();
改爲prototype測試
<bean id="student" class="cn.dota2.hero.Student" scope="prototype"> <property name="name" value="張三"/> </bean
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); Student student=(Student)ac.getBean("student"); Student student1=(Student)ac.getBean("student"); student.show(); student.setName("王五"); student.show(); student1.show();
一個bean文件可能須要引用其餘不少bean,這樣配置文件可能會很複雜,全部有了自動裝配來簡化spring。
常規引用this
package cq.school.student; import cq.school.School; public class Student { School school=null; public School getSchool() { return school; } public void setSchool(School school) { this.school = school; } public void show(){ school.getSchool(); } }
bean配置prototype
<bean id="frist" class="cq.school.FristSchool"/> <bean id="second" class="cq.school.SecondSchool"/> <bean id="student" class="cq.school.student.Student"> <property name="school" ref="frist"/>
自動裝配有幾種種code
<bean id="student" class="cq.school.student.Student" autowire="byName">
這裏的name是Student中的setSchoole中的school。它會在bean容器中尋找name相符合的自動裝配。因此須要更改frist或者second的id或者name。代碼以下xml
<bean id="school" class="cq.school.SecondSchool"/> <bean id="student" class="cq.school.student.Student" autowire="byName">
java代碼中給school賦值的方法時setSchool,因此會把id爲school傳給student。對象
<bean class="cq.school.FristSchool"/> <bean class="cq.school.SecondSchool"/> <bean id="student" class="cq.school.student.Student" autowire="byType"/>
和byname類似,會自動尋找類型相符合的裝配,測試一下
報錯緣由是由於一中和二中都是符合類型的,要刪除一個才行,用bytpye裝配須要整個容器只有一個相符合的類型。刪除一個後
<bean class="cq.school.SecondSchool"/> <bean id="student" class="cq.school.student.Student" autowire="byType"/>
若是全部配置都須要用到一種配置方式,能夠在頭文件中加入default-autowire="byName"。或者換成其餘配置方法
<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-2.5.xsd" default-autowire="byName">
經過構造器注入。適用於bytype得而方式裝配構造器,修改一下student的代碼,去掉set方法,讓它在構造方法裏面設置school。
package cq.school.student; import cq.school.School; public class Student { School school=null; public Student(School school){//修改處 this.school=school; } public School getSchool() { return school; } public void show(){ school.getSchool(); } }
自動裝配改爲改爲constructor注入
<?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-2.5.xsd" default-autowire="byName"> <bean class="cq.school.SecondSchool"/> <bean id="student" class="cq.school.student.Student" autowire="constructor"/> </beans>
結果同樣。
在配置bean時,有 scope屬性,能夠配置bean做用域,在整合struts2和spring時,須要將action設爲scope=「prototype」;(目前不知道爲啥,反正記住),關於自動裝配,用於減小配置文件。我本身感受自動裝配雖然簡潔了代碼,可是太過簡潔反而不利於閱讀,特別是bytype裝配,bean一旦太多,就容易出bug,並且很差排查。建議少用。