1.通過類的無參構造創建對象
當用最普通方式配置一個<bean>時,默認就是採用類的無參構造創建對象。在Spring容器初始化時,通過<bean>上配置的class屬性反射得到字節碼對象,通過newInstance()創建對象。
(詳細的創建方式,參見:https://blog.csdn.net/qq_32224047/article/details/106957319
newInstance()創建對象過程:
Class c = Class .forName("類的全路徑名稱")
Object obj = c.newInstance()
查詢API找到Class類的newInstance方法
查閱API說明(newInstance()方法的本質就是利用這個類的無參構造器創建了一個對象,並返回給你)
這種方式下spring創建對象,要求類必須有無參的構造,否則無法通過反射創建對象,會拋出異常。
2.通過類的有參構造創建對象
有上面的異常引出了有參構造創建對象,下面將進行驗證:
Person類中添加有參構造
public class Person {
/**
*添加有參數構造器
*/
public Person(String name,Dog dog) {
System.out.println("name:"+name+"|dog:"+dog+"|"+this);
}
/**
* person的eat方法
*/
public void eat(){
System.out.println("eating...");
}
}
執行拋出異常:BeanInstantiationException
注意觀察的話,編譯器也會檢查出配置文件並提示異常
解決上述問題的方法:只需要配置時指定讓spring去使用有參構造器即可
使用標籤爲:constructor-arg
標籤中的參數:
name--參數名,type--參數類型,index--參數位置(從0開始),value--參數值(直接賦值),ref--參數值(引用其他bean)
注意:
- value 和ref 只能用一個
- 參數可以只配置一部分,不用都配置(能確認出那個參數就行,也可以都寫全,準確定位)
- 引用類型用ref,指定後就不在用newinstance 方法,當容器解析到constructor-arg標籤時,會去調用Class的getConstructor(類<?>... parameterTypes) 方法,返回一個 Constructor對象
有參構造器創建對象過程:
1.通過getConstructor 創建getConstructor的對象
Constructor cs = getConstructor(xxxx)
2.通過該對象去調用newInstance()方法創建對應類的對象
Person obj = cs.newInstance(xxxxx)
代碼示例:
在applicationContext.xml中配置 constructor-arg,爲了方便觀察,並使用value和ref 給參數賦值,ref 傳入Dog類
<?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 id="person" class="cn.ww.beans.Person">
<constructor-arg name="name" type="java.lang.String" index="0" value="張三"/>
<constructor-arg name="age" type="int" index="1" value="18"/>
<constructor-arg name="dog" type="cn.ww.beans.Dog" index="2" ref="dog"/>
</bean>
<bean id="dog" class="cn.ww.beans.Dog"/>
</beans>
Person類:
package cn.ww.beans;
public class Person {
/**
*添加有參數構造器
*/
public Person(String name,int age,Dog dog) {
System.out.println("name:"+name+"age:"+age+"|dog:"+dog+"|"+this);
dog.walk();
}
/**
* person的eat方法
*/
public void eat(){
System.out.println("eating...");
}
}
Dog類
package cn.ww.beans;
public class Dog {
public void walk(){
System.out.println("dog is walking...");
}
}
測試驗證spring 創建對象,調用方法成功