Spring 2:IOC
※ 1. Spring IOC(must):※ IOC:Inversion of Control 控制反轉 一種說法:物件之間的依賴關係,由容器在執行時依據配置檔案動態的建立 另一種說法:物件的控制器轉移了,轉到外部容器了,避免了程式碼的糾纏,程式碼更 容易被維護,模板之間的耦合性降低,容易測試 IoC 控制反轉意味著將你設計好的類交給容器去控制,而不是在類的內部進行控制,即控制權由 應用程式碼中轉到了外部容器 IoC:包括兩部分內容 ※ DI:Dependency Injection依賴注入
元件不做定位查詢,只提供相應方法,由容器建立物件,並呼叫相應方法設定所需物件需要的元件
第三方(Spring) 2.你需要什麼(將需要的寫成全域性變數) 3.怎麼放入(給全域性變數賦值:1.set方法,2.構造器) 1.程式自身 我是誰(告訴Spring:全包名+類名) xml <bean class=“com.briup.UserService”>//指明service <property name=“dao” ref=“da”/>//需要dao </bean> <bean name=“da” class=“com.briup.UserDao”>//指明dao 注意:servlet是由Tomcat構建的,不能通過這種方式指明(框架的整合,有servlet與service結合的jar包)(寫註解方式)
※ (不要求)DL:Dependency Lookup依賴查詢
容器建立物件並提供回撥介面和上下文環境給元件,需要時通過介面從容器中查詢物件 依賴查詢,現在使用不太多。(EJB使用的更多,將物件建立好後,放到容器中。)
Spring IOC:依賴查詢(主動的找) 高內聚,低耦合 解決依賴問題:(建立工廠) public calss BeanFactory{ static final String SERVICE="service"; static final String DAO="dao"; public static Object getBean(String msg){ if(msg=="service"){ new Service(); }else{ new Dao(); } } } 呼叫時不再new物件 Class RegisterSer{ doGet(){ String name=Request.getParameter(“name”) String passwd=Request.getParameter(“passwd”) … UserService ser=BeanFactory.getBean(BeanFactory.SERVICE); ser.register(name,passwd…); } } //service層 Class UserService{ public void register(String name,String passwd…){ … UserDao dao=BeanFactory.getBean(BeanFactory.DAO); dao.saveUser(name,passwd…); } } //dao層 Class UserDao{ saveUser(String name,String passwd…); } 構建配置檔案(pro.properties) 維護全包名類名 方法一:靜態程式碼塊 dao=com.briup.Dao.UserDao service=com.briup.Service.UserService public calss BeanFactory{ static final String SERVICE="service"; static final String DAO="dao"; static Properties pro=null; static { pro=new Properties(); pro.load(new FileNputStream(new File("pro.perties"))); } public static Object getBean(String msg){ if(msg=="service"){ Class.forName(pro.getProgerty("service")).newInstance(); }else{ Class.forName(pro.getProgerty("dao")).newInstance(); } } } 方法二:靜態方法 public calss BeanFactory{ static final String SERVICE="service"; static final String DAO="dao"; public static Properties getPro(){ if(pro==null){ pro=new Properties(); pro.load(new FileNputStream(new File("pro.perties"))); } return pro; } public static Object getBean(String msg){ getPro(); if(msg=="service"){ Class.forName(pro.getProgerty("service")).newInstance(); }else{ Class.forName(pro.getProgerty("dao")).newInstance(); } } } 更改dao和service時,只用更改properties檔案中的value(全包名)值。
IOC解決:物件誰來建立的問題 DI解決:物件間的關係如何建立的問題。 org.springframework.beans及org.springframework.context包是IOC容器的基礎 =================================================※ 2. SpringIOC核心API - BeanFactory介面和容器 BeanFactory是Spring中Bean容器,IoC的核心介面,主要用於處理Bean的初始化和配置, 建立物件間的依賴關係 定義瞭如下方法:
Object getBean(String name) //根據指定名稱返回一個Bean例項
<T> T getBean(Class<T> requiredType)
//返回一個與給定Class唯一匹配的Bean例項
<T> T getBean(String name, Class<T> requiredType)
Object getBean(String name, Object... args)
Class<?> getType(String name) //得到名稱為name的Bean的Class物件
boolean isPrototype(String name) //判斷名稱為name的Bean是否是原型,
即是否總是返回一個新例項
boolean isSingleton(String name) //判斷名稱為name的Bean是否是單例
boolean containsBean(String name) //判斷是否包含給定名稱的Bean例項
boolean isTypeMatch(String name, Class<?> targetType)
//判斷名稱為name的Bean例項是否為targetType型別
String[] getAliases(String name) //如果名稱為name的Bean有別名返回
通過getBean方法便可以得到相應的類例項,但是最好永遠不呼叫,而使用注入, 避免對Spring API的依賴 在Spring中,同一Spring容器中的bean預設情況下是Singleton(單例),將在bean 的作用域介紹.
ApplicationContext介面 該介面繼承於BeanFactory,增強了BeanFactory,提供了事務處理AOP,國際化,事件傳遞
1.介面型Dao,Service
bean包:
package com.briup.bean;
public class UserDao {
}
package com.briup.bean;
public class UserService {
private UserDao dao;
public UserService() {
System.err.println("-------");
}
public UserService(UserDao dao) {
this.dao=dao;
}
public UserDao getDao() {
return dao;
}
public void setDao(UserDao dao) {
this.dao = dao;
}
}
IOC包:
<?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構建物件
name指的是構建物件的名字
class指向構建物件的全限定名
us=Class.forName("com.briup.bean.UserService").newInstance();
scope屬性:控制的是物件建立的是不是單例物件
prototype 原型別(非單例)
singleton 預設單例-->
<bean name="us" class="com.briup.bean.UserService"
scope="prototype">
<!-- property決定給當前物件設定屬性的方式採用set拼接name屬性setDao()
引數是基本資料型別value屬性指明,
物件用ref指明-->
<property name="dao" ref="ud"></property>
</bean>
<bean name="ud" class="com.briup.bean.UserDao"></bean>
</beans>
測試類:
@Test
public void ioc_test() {
try {
//啟動Spring容器,載入配置檔案,構建物件
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext("com/briup/IOC/ioc.xml");
//getBean()方法從容器中獲取物件
//預設情況下Spring構建的都是單例物件
UserService ser=(UserService) cp.getBean("us");
UserService ser1=cp.getBean(UserService.class);
UserService ser2=cp.getBean("us",UserService.class);
System.out.println(ser);
//isPrototype判斷Spring容器中物件是不是原型別
System.out.println(cp.isPrototype("us"));//true
System.out.println(cp.isPrototype("ud"));//false
//isSingleton判斷Spring容器中物件是不是單例物件
System.out.println(cp.isSingleton("us"));//false
System.out.println(ser.getDao());
System.out.println(cp.getBean("ud"));
//System.out.println(ser1);
//System.out.println(ser2);
} catch (BeansException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
=================================================※ 3. 配置檔案 配置Spring通過讀取配置元資料來對應用中各個物件進行例項化,配置以及組裝,通常使用 XML檔案來作為配置元資料的描述格式 可以將XML配置分別寫在多個檔案中 可以將多個配置放在一個String陣列中傳遞給容器進行初始化
eg: ApplicationContext ac = new ClassPathXmlApplicationContext(
new String[]{"services.xml","daos.xml"})
也可以在XML中使用<import resource="" />來進行匯入
XML基本結構如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=".....">
<bean id=".." class="..." >
<property name="..." ... />
</bean>
...
</beans>
容器的初始化和ClassPathXmlApplicationContext ClassPathXmlApplication實現ApplicationContext,用於讀取Xml初始化上下文,初始化方法如下: ApplicationContext ac = new ClassPathXmlApplicationContext(".../path/beans.xml"); 與Hibernate類似,不同的是Spring沒有預設的配置檔案
=================================================※ ※ 4. IOC注入(需要,第三方容器給你)1)setter方式(必須依靠無參構造器) A、基本型別(8中基本型別+字串)的裝配 B、物件型別的裝配 C、集合的裝配
類中是基本資料型別
set方式
Value屬性給基本資料型別賦值(String)
<property name=“” value=“”>
類中有類型別
class UserService{
UserDao dao}
ref為屬性值的是bean物件構建類型別的名字
<property name=“dao” ref=“tt”>
<property name=“dao”>
<ref bean=“tt”/>
</property>
<property name=“dao”>
<bean class=“UserDao”>
</property>
<bean name=“tt” class=“UserDao”>
2.實體型別Student
bean包
package com.briup.bean;
public class Student {
private long id;
private String name;
private int age;
private String email;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", email=" + email + "]";
}
}
IOC包配置檔案:
<?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">
<!-- name屬性指的是Spring中儲存物件的名字,scope="prototype"設定單例物件時,不同名字構建的物件仍不同
name可以指向多個名字,中間逗號隔開
id標籤也是指的是Spring中儲存物件的名字,不能用逗號,
id中的名字是一個整體
-->
<bean id="student" name="stu,stu1,stu2" class="com.briup.bean.Student" scope="prototype">
<!-- 1.構建物件
2.設定屬性
setId 反射getDeclaredMethod("setId")
方法映象public void setId(long);
方法引數getParameterTypes()[long]
long id=Long.parseLong("1");
stu.setId(id);
-->
<property name="id" value="1"></property>
<property name="name" value="tom"></property>
<property name="age">
<value>33</value>
</property>
<property name="email" value="[email protected]"></property>
</bean>
<!-- 給某個名字對應物件起別名 -->
<alias name="stu" alias="studd"/>
</beans>
測試類:
@Test
public void setter_test() {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext("com/briup/IOC/setter.xml");
System.out.println(cp.getBean("stu"));
System.out.println(cp.getBean("stu1"));
System.out.println(cp.getBean("stu2"));
System.out.println(cp.getBean("student"));
}
A、基本型別的裝配 注意: 用setter方式注入的話,必須要用set、get方法 方式: 配置元素<value/>
例子:
public class HelloBean {
private String name;
private int age;
public String sayHello(){
return "hello "+name +",your age is" + age;
}
.............
}
配置檔案applicationContext.xml
<bean id="helloBean" class="ioc.HelloBean">
<property name="name">
<value>terry</value>
</property>
<property name="age" value="20">
</property>
</bean>
<!--id是Bean的唯一標識,要求在整個配置檔案中要唯一,也可使用name屬性
,bean標籤裡面的id和name屬性都可以用來標識這個配置的物件,
-->
<!--property 對於所有用setter方式來注入的必須用Property來指定-->
<!--value 是對以基本型別,都用value來注入,可以實現自動的資料型別轉換-->
測試類:
public class Test {
public static void main(String[] args) {
ApplicationContext ac =
new ClassPathXmlApplicationContext("ioc1applicationContext.xml");
//獲取容器的一個例項
HelloBean hb = (HelloBean) ac.getBean("helloBean");
System.out.println(hb.sayHello());
}
}
B. 物件型別的裝配 (1)、<ref local=" "/> (2)、<ref bean=" "/> (3)、使用property的ref屬性引用
public class OtherBean {
private String str1;
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String toString(){
return "OtherBean "+str1;
}
}
public class SomeBean {
private OtherBean ob;
public void printInfo(){
System.out.println("someBean "+ob);
}
public OtherBean getOb() {
return ob;
}
public void setOb(OtherBean ob) {
this.ob = ob;
}
}
配置applicationContext.xml
<bean id="someBean" class="ioc.SomeBean">
<property name="ob">
<ref bean="otherBean" />
</property>
</bean>
配置other.xml檔案
<bean id="otherBean" class="ioc2.OtherBean">
<property name="str1">
<value>string1</value>
</property>
</bean>
測試類:
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"ioc2//applicationContext.xml","ioc2//other.xml"});
SomeBean sb = (SomeBean) ac.getBean("someBean");
sb.printInfo();
}
rel.xml
<?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 name="us" class="com.briup.bean.UserService">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
1.porperty內屬性ref引入物件的名字(spring)
<property name="dao" ref="dap"></property>
</bean> -->
<bean name="us" class="com.briup.bean.UserService">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
<!-- ref引入物件的名字(spring) -->
<property name="dao" >
<!-- 2.ref便籤 -->
<ref bean="dap"/>
<!--有些版本(低)也支援
<ref local="dap"/> -->
</property>
</bean>
<bean name="us1" class="com.briup.bean.UserService">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
<!-- 3.ref引入物件的名字(spring) -->
<property name="dao">
<!-- bean標籤 -->
<bean name="dap" class="com.briup.bean.UserDao"></bean>
</property>
</bean>
<bean name="us2" class="com.briup.bean.UserService">
<property name="id" value="1"></property>
<property name="name" ref="str"></property>
<property name="dao">
<bean name="dap" class="com.briup.bean.UserDao"></bean>
</property>
</bean>
<bean name="str" class="java.lang.String">
<!-- 基於構造器方式注入
index表示該引數在當前物件構造器中的位置,角標從0開始
Class.forName("java.lang.String").newInstance("test")-->
<constructor-arg index="0" value="test"></constructor-arg>
</bean>
<bean name="dap" class="com.briup.bean.UserDao">
</bean>
</beans>
測試類:
@Test
public void rel_test() {
try {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext("com/briup/IOC/rel.xml");
UserService us=(UserService) cp.getBean("us2");
// UserService us1=
// cp.getBean("us",UserService.class);
System.out.println(us);
System.out.println(us.getName());
} catch (BeansException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
C. 集合的裝配 方式:配置元素<list> <set> <map> <props>
public class SomeBean {
private List listProperty;
private Set setProperty;
private Map mapProperty;
private Properties<String,String> property;
public List getListProperty() {
return listProperty;
}
public void setListProperty(List listProperty) {
this.listProperty = listProperty;
}
public Set getSetProperty() {
return setProperty;
}
public void setSetProperty(Set setProperty) {
this.setProperty = setProperty;
}
public Map getMapProperty() {
return mapProperty;
}
public void setMapProperty(Map mapProperty) {
this.mapProperty = mapProperty;
}
public Properties getProperty() {
return property;
}
public void setProperty(Properties property) {
this.property = property;
}
public void printInfo(){
System.out.println("listProperty");
System.out.println(listProperty);
System.out.println("setProperty");
System.out.println(setProperty);
Set set = mapProperty.entrySet();
Iterator it = set.iterator();
while(it.hasNext()){
Map.Entry entry = (Entry) it.next();
System.out.println("Key " +entry.getKey() );
System.out.println("value "+entry.getValue());
}
System.out.println("props: ");
Set set2 = property.entrySet();
Iterator it2 = set2.iterator();
while(it2.hasNext()){
Map.Entry entry= (Entry) it2.next();
System.out.println("key "+entry.getKey());
System.out.println("value "+entry.getValue());
}
}
}
applcationContext.xml的寫法:
<bean id="someBean" class="ioc.SomeBean">
<property name="listProperty">
<list>
<value>list1</value>
<value>list1</value>
<value>list3</value>
</list>
</property>
<property name="setProperty">
<set>
<value>set1</value>
<value>set1</value>
<value>set3</value>
</set>
</property>
<property name="mapProperty">
<map>
<entry key="key1">
<value>value1</value>
</entry>
<entry key="key2">
<value>value2</value>
</entry>
</map>
</property>
<property name="property">
<props>
<prop key="key1">prop1</prop>
<prop key="key2">prop2</prop>
<prop key="key3">prop3</prop>
</props>
</property>
</bean>
測試類:Test
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ac =
new ClassPathXmlApplicationContext("ioc3applicationContext.xml");
SomeBean sb = (SomeBean) ac.getBean("someBean");
sb.printInfo();
}
實體類:
package com.briup.bean;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class CollTest {
private String[] array;
private List<String> list;
private Set<String> set;
private Map<String, String> map;
private Properties pros;
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Properties getPros() {
return pros;
}
public void setPros(Properties pros) {
this.pros = pros;
}
}
IOC配置xml
<?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 name="str" class="java.lang.String">
<constructor-arg index="0" value="array5"></constructor-arg>
</bean>
<bean name="coll" class="com.briup.bean.CollTest">
<property name="array">
<list>
<value>array1</value>
<value>array2</value>
<value>array3</value>
<ref bean="str"/>
</list>
<!-- 陣列的裝配 array,list標籤都可以寫-->
<!-- <array>
<value>array1</value>
<value>array2</value>
<value>array3</value>
<ref bean="str"/>
<bean class="java.lang.String">
<constructor-arg index="0" value="array4"></constructor-arg>
</bean>
</array> -->
</property>
<property name="list">
<!-- list集合的裝配,spring預設構建的集合是ArrayList
在beans的scheme的約束下不能指定具體的構建什麼樣的集合,
util的scheme可以自定義集合型別
value-type指的是集合的型別-->
<!-- <array value-type="java.lang.String">
<value>list1</value>
<value>list2</value>
<value>list3</value>
</array> -->
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<property name="set">
<!-- set集合的裝配,標籤選擇set,預設構建的結合是LinkedHashSet -->
<set value-type="java.lang.String">
<value>set1</value>
<value>set2</value>
<value>set3</value>
<ref bean="str"></ref>
</set>
</property>
<property name="map">
<!-- map集合的裝配,預設構建的集合是LinkedHashMap
map下的entry表示一組鍵值對內容
entry屬性 key表示鍵(基本資料型別或String)key-ref表示鍵是物件 key-ref指向做鍵的物件名字(存在Spring中)
value表示基本資料型別的值(String)value-ref把Spring中某個名字的物件作為值 -->
<map key-type="java.lang.String" value-type="java.lang.String">
<entry key="key1" value="1"></entry>
<entry key="key2" value="2"></entry>
<entry key-ref="str" value-ref="str"></entry>
</map>
</property>
<property name="pros">
<!--properties集合的裝配 -->
<props value-type="java.lang.String">
<prop key="pro1">pro1</prop>
<prop key="pro2">pro2</prop>
<prop key="pro3">pro3</prop>
</props>
</property>
</bean>
</beans>
測試類:
public void coll_test() {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext("com/briup/IOC/coll.xml");
CollTest col=(CollTest) cp.getBean("coll");
System.out.println(col);
// String[] strs=col.getArray();
// System.out.println(Arrays.toString(strs));
// List<String> list=col.getList();
// System.out.println(list.getClass());
// System.out.println(list);
// Set<String> sets=col.getSet();
// System.out.println(sets.getClass());
// System.out.println(sets);
// Map<String, String> map=col.getMap();
// System.out.println(map.getClass());
// System.out.println(map);
Properties pro=col.getPros();
System.out.println(pro.getClass());
System.out.println(pro);
}
2.加util標籤庫
配置xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean name="str" class="java.lang.String">
<constructor-arg index="0" value="array5"></constructor-arg>
</bean>
<!-- Spring容器構建集合物件 id標籤表示集合的名字-->
<util:list id="strlist" list-class="java.util.LinkedList" value-type="java.lang.String">
<value>list1</value>
<value>list2</value>
<value>list3</value>
</util:list>
<bean name="de_coll" class="com.briup.bean.CollTest">
<property name="array">
<array>
<value>array1</value>
<value>array2</value>
<value>array3</value>
</array>
</property>
<property name="list" ref="strlist">
<!-- list-class指定Spring構建list集合的型別 -->
<!-- <util:list list-class="java.util.LinkedList" value-type="java.lang.String">
<value>list1</value>
<value>list2</value>
<value>list3</value>
</util:list> -->
</property>
<property name="set">
<!-- set-class指定Spring構建的set集合物件 -->
<util:set set-class="java.util.HashSet" value-type="java.lang.String">
<value>set1</value>
<value>set2</value>
<value>set3</value>
</util:set>
</property>
<property name="map">
<util:map map-class="java.util.HashMap">
<entry key="1" value="te1"></entry>
<entry key="2" value="te2"></entry>
<entry key="3" value="te3"></entry>
<entry key-ref="str" value-ref="str"></entry>
</util:map>
</property>
<property name="pros">
<!-- <props>
<prop key="pro1">pro</prop>
<prop key="pro2">pro</prop>
<prop key="pro3">pro</prop>
</props> -->
<!-- location直接將properties檔案的key=value內容載入到集合物件中,路徑也是基於classpath(src的下一級目錄開始) -->
<util:properties location="com/briup/IOC/db.properties"></util:properties>
</property>
</bean>
</beans>
測試類:
@Test
public void de_coll_test() {
try {
//ClassPathXmlApplicationContext構造器內參數是可變參,可以寫多個路徑
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext("com/briup/IOC/definecoll.xml");
// ClassPathXmlApplicationContext cp=
// new ClassPathXmlApplicationContext(new String[] {"com/briup/IOC/coll.xml","com/briup/IOC/de_coll.xml"});
CollTest col=(CollTest) cp.getBean("de_coll");
List<String> list=(List<String>) cp.getBean("strlist");
System.out.println(list);
System.out.println(col);
// String[] strs=col.getArray();
// System.out.println(Arrays.toString(strs));
// List<String> list=col.getList();
// System.out.println(list.getClass());
// System.out.println(list);
// Set<String> sets=col.getSet();
// System.out.println(sets.getClass());
// System.out.println(sets);
Map<String, String> map=col.getMap();
System.out.println(map.getClass());
System.out.println(map);
// Properties pro=col.getPros();
// System.out.println(pro.getClass());
// System.out.println(pro);
} catch (BeansException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2)基於構造器
方式: 配置<constructor-arg>元素 在Bean中不用寫set方法,但是要有相應的構造器
過載:個數,型別,順序
<constructor-arg type="int" value="">
<constructor-arg index="0" value="">
例子:
public class SomeBean {
//構造器配置
private String str1;
private String str2;
private int value1;
public SomeBean(String str1, String str2, int value1) {
super();
this.str1 = str1;
this.str2 = str2;
this.value1 = value1;
}
public void printInfo(){
System.out.println("str1 "+str1 +"str2 "+str2+" value1 "+value1 );
}
}
配置檔案applicationContext.xml的寫法
<bean id="someBean" class="ioc.SomeBean">
方式一:使用型別注入
<constructor-arg type="java.lang.String">
<value>String1</value>
</constructor-arg>
<constructor-arg type="java.lang.String" value="String2">
</constructor-arg>
<constructor-arg type="int">
<value>100</value>
</constructor-arg>
方式二:使用引數的索引注入
<constructor-arg index="1"> <!--表示第二個引數-->
<value>String1</value>
</constructor-arg>
<constructor-arg index="0">
</constructor-arg>
<constructor-arg index="2">
<value>100</value>
</constructor-arg>
</bean>
配置xml
<?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">
<!-- 基於構造器給Spring構建的物件傳參,使用的子標籤constructor-arg-->
<bean name="stu" class="com.briup.bean.Student">
<!-- 1.基於角標傳引數,角標從0開始,角標代表的是賦值的位置
配置constructor-arg位置不會影響賦值 -->
<constructor-arg index="0" value="11"></constructor-arg>
<constructor-arg index="1" value="tom"></constructor-arg>
<constructor-arg index="2" value="30"></constructor-arg>
<constructor-arg index="3" value="[email protected]"></constructor-arg>
</bean>
<!-- 2.基於構造器引數的型別配置
基本資料型別直接寫型別-->
<bean name="stu1" class="com.briup.bean.Student">
<!-- type屬性要和構造器中設定引數的型別匹配(long,String,int,String)
基於型別匹配構造器不能換位置 -->
<constructor-arg type="long" value="11"></constructor-arg>
<constructor-arg type="java.lang.String" value="tom1"></constructor-arg>
<constructor-arg type="int" value="33"></constructor-arg>
<constructor-arg type="java.lang.String" value="[email protected]"></constructor-arg>
</bean>
<!-- 3.基於構造器中的變數名設定值
name指向構造器中的變數名-->
<bean name="stu2" class="com.briup.bean.Student">
<constructor-arg name="id" value="33"></constructor-arg>
<constructor-arg name="name" value="jake"></constructor-arg>
<constructor-arg name="age" value="12"></constructor-arg>
<constructor-arg name="email" value="[email protected]"></constructor-arg>
</bean>
<!-- 上面三種結合 -->
<bean name="stu3" class="com.briup.bean.Student">
<constructor-arg index="0" name="id"><value>11</value></constructor-arg>
<constructor-arg index="1" name="name" ref="str"></constructor-arg>
<constructor-arg index="2" name="age" value="34"></constructor-arg>
<constructor-arg index="3" name="eamil"><ref bean="str"></ref></constructor-arg>
</bean>
<bean id="str" class="java.lang.String">
<constructor-arg index="0" value="kks"></constructor-arg>
</bean>
</beans>
測試類:
@Test
public void construct_test() {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext("com/briup/IOC/construct.xml");
Student s=(Student) cp.getBean("stu2");
System.out.println(s);
}
3)自動裝配 :容器依照一些規則去裝配bean中的一個屬性 在beans標籤中配置裝載方式:default-autowire="byName" 或者在bean標籤中指定配置方式 a. autowire="byName": spring容器會到當前的類中找property的名字,然後 再根據這個名字去spring容器中找有沒有和這個property 名字相同的物件,有的話,就把這個物件當做引數放到 setXxxx這個方法裡面注入進來. 注意:瞭解property指的類中的什麼東西。
b,autowire="byType": spring容器會根據當前類中的set方法裡面引數的型別, 去容器中找相匹配的物件,如果沒找到就算了,如果找到 一個就注入進來,如果找到多個,那麼就會報錯了. c,autoWirde = "constructor" 根據構造器的引數型別去匹配 如果所有屬性(基本型別) d,autoWire = "autoDetect" 自動檢測 e.autowire = "default"
例子:
public class SomeBean {
//自動裝配
private String str2;
private OtherBean ob;
public SomeBean(OtherBean ob) {
super();
this.ob = ob;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
public OtherBean getOb() {
return ob;
}
public void setOb(OtherBean ob) {
this.ob = ob;
}
public void printInfo(){
System.out.println("str2 "+str2 +" ob "+ob);
}
}
public class OtherBean {
//自動裝配
private String str1;
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "str1 "+str1;
}
}
配置檔案的寫法
<bean id="otherBean" class="ioc.OtherBean">
<property name="str1" value="String1" />
</bean>
<!-- <bean id="someBean" class="ioc.SomeBean" autowire="byName">
<property name="str2" value="String2" />
</bean>
<bean id="someBean" class="ioc.SomeBean" autowire="byType">
<property name="str2" value="String2" />
</bean>
<bean id="someBean" class="ioc.SomeBean" autowire="constructor">
<property name="str2" value="String2" />
</bean>
配置xml
<?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"
default-autowire="byName">
<!-- autowire自動匹配,自動轉載
byType基於型別匹配並轉載,特點:基於set方法的引數型別匹配,使用byType時,必須保證該型別只能出現一次
byName基於名字匹配,特點:基於set後首字母小寫的名字和bean標籤中的名字匹配
default採用預設的,前提:和一級標籤beans中的屬性default-autowire結合使用
default-autowire設定的是全域性的匹配方式
如果bean標籤配置 類匹配物件的方式,一級標籤配置的 default-autowire失效(就近原則)
autowire="no" 不採用自動匹配 -->
<!-- <bean name="us" class="com.briup.bean.UserService" autowire="byType">
</bean> -->
<!-- <bean name="us" class="com.briup.bean.UserService" autowire="byName">
</bean> -->
<bean name="us" class="com.briup.bean.UserService" autowire="default">
</bean>
<bean name="dao1" class="com.briup.bean.UserDao">
<property name="id" value="101"></property>
</bean>
<bean name="dao" class="com.briup.bean.UserDao">
<property name="id" value="100"></property>
</bean>
<!--autowire="constructor"基於構造器中的引數匹配,預設基於型別匹配,如果型別找到多個的時候,再基於名字匹配 -->
<bean name="us1" class="com.briup.bean.UserService" autowire="constructor">
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" value="tom"></constructor-arg>
<constructor-arg index="2" value="dao"></constructor-arg>
</bean>
</beans>
測試類:
@Test
public void auto_test() {
try {
ClassPathXmlApplicationContext cp=
new ClassPathXmlApplicationContext("com/briup/IOC/auto.xml");
UserService ser=(UserService) cp.getBean("us");
System.out.println(ser);
System.out.println(ser.getDao());
} catch (BeansException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
注意:自動裝配的優先順序低於手動裝配 自動裝配一般用於快速開發建立系統原型的情況,但是在正式的開發中很少使用, 因為容易出錯,難以維護;
4)繼承裝入: 並不是oo的繼承關係 (bean的定義的繼承,指bean的配置可去繼承 True 抽象化 客戶端不能getBean了 Abstract = False 預設 Parent = "父類bean的id"
例子:
public class Car {
//bean的定義的繼承
private String owner;
private String name;
private int price;
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return owner+" "+name+" "+price;
}
}
<bean id="abstractCar" class="ioc.Car" abstract="true">
<property name="owner" value="zwb" />
</bean>
<bean id="car1" parent="abstractCar">
<property name="name" value="qq" />
<property name="price" value="10" />
</bean>
<bean id="car2" parent="abstractCar">
<property name="name" value="baoma" />
<property name="price" value="70" />
</bean>
public class Test {
public static void main(String[] args){
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc6applicationContext.xml");
Car car1=(Car) ac.getBean("car1");
Car car2=(Car) ac.getBean("car2");
System.out.println(car1.toString());
System.out.println(car2.toString());
}
}
======================================================= 8,建立Bean例項的方式 1) 通過構造器(有參或無參) 方式: <bean id="" class=""/>
2) 通過靜態工廠方法 方式: <bean id/name="目標物件" class="工廠類" factory-method="靜態工廠方法"/> 注意:工廠類不會被例項化 利用靜態factory方法建立,可以統一管理各個bean的建立,如各個bean在建立之前需要相同 的初始化處理,則可用這個factory方法險進行統一的處理等等。 例子: public class HelloBeanFactory { public static HelloBean createHelloBean() { return new HelloBean(); } } xml:配置 //構造器配置 ﹤bean id="sayhello" class="test.service.impl.HelloBean"/﹥ //靜態工廠 ﹤bean id="sayhello2" class="test.service.impl.HelloBeanFactory" factory-method="createHelloBean"/﹥ 3)通過例項工廠方法(非靜態方法) 方式: <bean id="factory" class="工廠類"/> <bean id="" factory-bean="factory" factory-method="例項工廠方法"/> 利用例項化factory方法建立,即將factory方法也作為了業務bean來控制
工廠Java檔案: public class HelloBeanInstanceFactory { public Hello createHelloBean() { return new HelloBean(); } xml: ﹤bean id="factory" class="test.service.impl.HelloBeanInstanceFactory"/﹥ ﹤bean id="sayhello" factory-bean="factory" factory-method="createHelloBean"/﹥
4)Bean實現Spring提供FactoryBean介面 介面提供工廠方法和返回構建物件的Class以及是否單例的方法 注意: <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="com/briup/ioc/factory/db.properties"></property> </bean> <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="location" value="com/briup/IOC/static.properties"></property> </bean>
=================================================
9,SpringBean類的生命週期 在ApplicationContext中Bean的生命週期
生命週期執行的過程如下: 1)需找所有的bean根據bean定義的資訊來例項化bean 預設bean都是單例 2)使用依賴注入,spring按bean定義資訊配置bean的所有屬性 3若bean實現了BeanNameAware介面,工廠呼叫Bean的setBeanName()方法傳遞bean的ID。 4)若bean實現了BeanFactoryAware介面,工廠呼叫setBeanFactory() 方法傳入工廠自身。 5)若bean實現了ApplicationContextAware()介面,setApplicationContext()方法會被呼叫 6)若bean實現了InitializingBean,則 afterPropertiesSet被呼叫 7)若bean指定了init-method="init"方法,它將被呼叫。 8)若BeanPostProcessor和bean關聯, 則它們的postProcessBeforeInitialization()方法被呼叫 9)、若有BeanPostProcessor和bean關聯, 則它們的postProcessAfterInitialization()方法被呼叫 注意:通過已上操作,此時的Bean就可以被應用的系統使用,並將保留在BeanFactory工廠中直到不再需要為止.但我們也可以通過10或者11進行銷燬 10)、若bean實現了DisposableBean介面,distroy()方法被呼叫 11)、如果指定了destroy-method="close"定製的銷燬方法,就呼叫這個方法