spring創建對象的方式
spring可以幫助管理對象,需要的時候從spring容器中獲取相應的對象即可,那么spring究竟是怎樣創建對象的呢?下面介紹三種創建對象的方式
無參構造的方法(重點)
首先創建一個User類
public class User { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
然后在配置文件中配置相應的bean元素
<bean name="user" class="com.jinxin.spring.User"></bean>
最后獲取該對象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) ac.getBean("user");
靜態工廠(了解)
首先創建一個User類,其中有一個靜態方法 createUser() 是用來獲取User對象的
public class User { private String name; private Integer age; public static User createUser() { return new User(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
然后在配置文件中配置調用createUser()方法來創建User對象放到容器中
1 <bean name="user1" class="com.jinxin.spring.User" factory-method="createUser"></bean>
獲取該對象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) ac.getBean("user1");
實例化工廠(了解)
首先創建一個User類,里面有一個非靜態方法 createUser() 用來獲取對象
public class User { private String name; private Integer age; public User createUser() { return new User(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
然后在配置文件中配置調用createUser()方法來獲取User對象
1 <bean name="user2" factory-bean="userFactory" factory-method="createUser1"></bean> 2 <bean name="userFactory" class="com.jinxin.spring.User"></bean>
最后獲取該user對象
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) ac.getBean("user2");
Spring屬性注入
spring屬性的注入分為四種,分別是
- set方法注入(重點)
- 構造方法的注入(重點)
- p名稱空間注入(了解)
- spel注入(了解)
set方法注入
首先准備一個User類,里面有name,age以及car屬性,其中Car是一個類,里面有name跟color屬性
User類
public class User { private String name; private Integer age; private Car car; @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
Car類
public class Car { private String name; private String color; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } }
為User對象的name跟age屬性注入值
使用property標簽注入,其中name書要注入的屬性名,value是為該屬性注入什么值
1 <bean name="user" class="com.jinxin.spring.User"> 2 <property name="name" value="Eric"></property> 3 <property name="age" value="16"></property> 4 </bean>
為User對象的car屬性注入值
上面介紹了為User的基本類型屬性注入值,那么如果還有一個屬性是自己定義的某一個類呢?還能使用同樣的方式注入嗎?當然不能,首先,應該先寫出該類(Car類)的bean元素,然后在user的bean元素里面使用property標簽進行注入,值得注意的是,property中的value字段應該替換成ref字段
1 <!-- 先配置car --> 2 <bean name="car" class="com.jinxin.spring.Car"> 3 <property name="name" value="蘭博基尼"></property> 4 <property name="color" value="yellow"></property> 5 </bean> 6 7 <bean name="user" class="com.jinxin.spring.User"> 8 <!-- 然后使用ref關聯上面的car對象 --> 9 <property name="car" ref="car"></property> 10 </bean>
構造方法的注入
在上面的User類中加入構造方法設置name,age跟car屬性
public class User { private String name; private Integer age; private Car car; public User(String name, Integer age, Car car) { this.name = name; this.age = age; this.car = car; } @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
然后在配置文件中注入值
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="蘭博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User"> 7 <constructor-arg name="name" value="Scarlett"></constructor-arg> 8 <constructor-arg name="age" value="33"></constructor-arg> 9 <constructor-arg name="car" ref="car"></constructor-arg> 10 </bean>
上面通過constructor-arg標簽就可以為構造方法注入屬性值,但是這還不夠,現在如果有兩個構造方法,形參的數目類型一致,只是位置不同,那么該怎樣確定究竟為那個構造方法注入屬性值呢?這時需要引入一個新的字段,叫做index,通過指定參數的位置來確定執行哪一個構造方法
首先為User類指定兩個構造方法,形參數目類型均一致
public class User { private String name; private Integer age; private Car car; public User(String name, Integer age, Car car) { this.name = name; this.age = age; this.car = car; System.out.println("構造一"); } public User(Integer age, String name, Car car) { this.name = name; this.age = age; this.car = car; System.out.println("構造二"); } @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
然后在配置文件中通過指定參數的位置來確定執行哪一個構造方法
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="蘭博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User"> 7 <constructor-arg name="name" value="Scarlett" index="1"></constructor-arg> 8 <constructor-arg name="age" value="33" index="0"></constructor-arg> 9 <constructor-arg name="car" ref="car" index="2"></constructor-arg> 10 </bean>
很顯然,上面設置的參數順序是age、 name、car,所以應該執行構造方法二
上面雖然通過確定參數的位置解決了確定參數類型數目相同的構造方法的問題,那么如何解決參數位置數目相同但是類型不同的問題呢?這需要引入另外一個字段type來指定參數的類型
首先在User類中准備兩個構造方法,參數的數目以及位置都一致,只是一個name的類型是String,另一個name的類型是Integer
public class User { private String name; private Integer age; private Car car; public User(String name, Integer age, Car car) { System.out.println("構造一"); } public User(Integer name, Integer age, Car car) { System.out.println("構造二"); } @Override public String toString() { // TODO Auto-generated method stub return this.name + "-" + this.age + "-" + this.car.getName() + "-" + this.car.getColor(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } }
然后在配置文件中通過指定參數的類型來確定執行哪一個構造方法
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="蘭博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User"> 7 <constructor-arg name="name" value="100" type="java.lang.Integer"></constructor-arg> 8 <constructor-arg name="age" value="33"></constructor-arg> 9 <constructor-arg name="car" ref="car"></constructor-arg> 10 </bean>
很顯然,上面執行的應該是name為Integer屬性的構造方法
上面通過index跟type便能夠具體到每一個構造方法
p命名空間注入(了解)
首先需要在beans里面導入p名稱:xmlns:p="http://www.springframework.org/schema/p"
即
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://www.springframework.org/schema/beans" 4 xmlns:p="http://www.springframework.org/schema/p" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> 6 7 </bean>
然后在bean元素里面通過 p:屬性名 進行注入
1 <bean name="car" class="com.jinxin.spring.Car"> 2 <property name="name" value="蘭博基尼"></property> 3 <property name="color" value="yellow"></property> 4 </bean> 5 6 <bean name="user" class="com.jinxin.spring.User" p:name="taylor" p:age="27" p:car-ref="car"></bean> 7
spel注入(了解)
spel:spring expression language(spring表達式語言)
1 <bean name="user" class="com.jinxin.spring.User"> 2 <property name="name" value="Sam"></property> 3 <property name="age" value="18"></property> 4 </bean> 5 6 <bean name="car" class="com.jinxin.spring.Car"> 7 <property name="name" value="蘭博基尼"></property> 8 <property name="color" value="yellow"></property> 9 </bean> 10 11 <!-- 將user的name屬性的值作為user1的name屬性的值 --> 12 <bean name="user1" class="com.jinxin.spring.User"> 13 <property name="name" value="#{user.name}"></property> 14 <property name="car" ref="car"></property> 15 </bean>
復雜類型注入
如果出現以下類型,應該怎樣注入呢?
private Object[] arry; // 數組類型 private List list; // List類型 private Map map; // Map類型 private Properties prop;
這涉及到了復雜類型的注入,下面一一介紹注入方式
數組類型的注入
<bean name="" class=""> <property name="arry"> <array> <value>sxy</value> <value>nn</value> <ref bean="car" /> </array> </property> </bean>
List類型注入
<bean name="" class=""> <property name="list"> <list> <value>jack</value> <value>rose</value> <ref bean="car" /> </list> </property> </bean>
Map類型注入
<bean name="" class=""> <property name="map"> <map> <entry key="url" value="jdbc:mysql:///1806"></entry> <entry key="car" value-ref="car"></entry> <entry key-ref="car" value-ref="car"></entry> </map> </property> </bean>
properties注入
<bean name="" class=""> <property name="prop"> <props> <prop key="url">jdbc:mysql:///1806</prop> <prop key="driverClass">com.jdbc.mysqlDriver</prop> <prop key="userName">root</prop> </props> </property> </bean>
Bean元素
使用bean元素可以描述需要Spring容器管理的對象
name屬性
給被管理的對象起個名字,獲得對象時根據名稱獲取對象,可以重復,可以使用特殊字符
class屬性
被管理對象的完整類名
id屬性
與name屬性作用一模一樣,但是名稱不能重復,不能使用特殊字符,在開發中應該盡量使用name屬性
scope屬性
<bean name="user" class="com.jinxin.bean.User" scope="singleton"></bean>
scope屬性指定了創建對象的規則,一共有四個取值,分別是singletom、prototype、request、session
- singleton(重點,默認值):單例對象,被標識為單例的對象在Spring容器中只會創建一次
- prototype(重點):多例,被標識為多例的對象每次獲得時才會創建,每次創建都是新的對象
- request(了解):在web環境下,對象與request生命周期一致
- session(了解):在web環境下,對象與session生命周期一致
注意:將struts2的action交給spring管理的時候,scope必須是prototype,因為每次請求都會創建一個新的action對象
初始化&銷毀方法
配置一方法作為生命周期初始化方法,Spring會在對象創建之后立即調用
init-method (方法必須是 public void 類型)
配置一個方法作為生命周期的銷毀方法,Spring關閉並銷毀所有的對象前調用
destory-method (方法必須是 public void 類型)
准備一個User類,類中有兩個方法分別作為初始化方法跟銷毀方法
public class User{ public void init(){ System,out,println("我是初始化方法"); } public void destory(){ System,out,println("我是銷毀方法"); } }
在配置文件中指定這兩個方法為初始化方法跟銷毀方法
1 <bean name="user" class="com.jinxin.spring.User" init-method="init" destory-method="destoey"></bean>
分模塊化配置
在spring中,講所有的bean元素都配置在一個文件里面,難免會很亂,將特定模塊下的對象配置在特定的文件里面,最后將這些文件全部引入到src目錄下的applicationContext.xml文件中即可
<import resource="com/jinxin/spring/user.xml">