Spring框架(二)反射機制, 注入, 單例模式, 自動裝載, 延遲載入
Spring反射機制:
1, 通過spring來獲取一個物件的例項
1 <bean id="user" class="com.model.User">
2
3 </bean>
1 ApplicationContext ac=new ClassPathXmlApplicationContext("Spring-all.xml");//呼叫此方法時類已經例項化好了
2 User u=(User)ac.getBean("user");//拿到例項化的類
2, 通過spring進行屬性注入 setter方法注入
1 <!-- 通過Spring給類注入屬性,通過空參構造方法 --> 2 <property name="username"> 3 <value>hanqi</value> 4 </property> 5 <property name="password"> 6 <value>123</value> 7 </property>
構造器注入
1 <!--
2 另一種通過帶參構造方法-->
3 <constructor-arg index="0" value="name1"></constructor-arg>
4 <constructor-arg index="1" value="pwd1"></constructor-arg>
5
介面注入
1 public class ClassA { 2 private InterfaceB clzB; 3 public init() { 4 Ojbect obj = 5 Class.forName(Config.BImplementation).newInstance(); 6 clzB = (InterfaceB)obj; 7 } 8 …… 9 }
上面的程式碼中,ClassA依賴於InterfaceB的實現,如何獲得InterfaceB實現類的例項?傳統的方法是在程式碼中建立InterfaceB實現類的例項,並將起賦予clzB。
而這樣一來,ClassA在編譯期即依賴於InterfaceB的實現。為了將呼叫者與實現者在編譯期分離,於是有了上面的程式碼,我們根據預先在配置檔案中設定的實現類的類名,動態載入實現類,並通過InterfaceB強制轉型後為ClassA所用。 這就是介面注入的一個最原始的雛形。 而對於一個Type1型IOC容器而言,載入介面實現並建立其例項的工作由容器完成,如J2EE開發中常用的Context.lookup(ServletContext.getXXX),都是Type1型IOC的表現形式。 Apache Avalon是一個典型的Type1型IOC容器。
p標記的使用 <bean p:username=""></bean>
1 <bean id="user" class="com.model.User" p:username="pusername" p:password="ppwd">
2 </bean>
3, 將一個物件注入到另一個物件<ref bean="...">
使用者有一個部門
部門有多個使用者
model:
1 package com.model;
2
3 public class User {
4 private String username;
5 private String password;
6 private Dept dept;
7
8
9 public User() {
10 super();
11 // TODO Auto-generated constructor stub
12 }
13 public User(String username, String password, Dept dept) {
14 super();
15 this.username = username;
16 this.password = password;
17 this.dept = dept;
18 }
19 public String getUsername() {
20 return username;
21 }
22 public void setUsername(String username) {
23 this.username = username;
24 }
25 public String getPassword() {
26 return password;
27 }
28 public void setPassword(String password) {
29 this.password = password;
30 }
31 public Dept getDept() {
32 return dept;
33 }
34 public void setDept(Dept dept) {
35 this.dept = dept;
36 }
37 @Override
38 public String toString() {
39 return "User [username=" + username + ", password=" + password + ", dept=" + dept + "]";
40 }
41
42
43 }
1 package com.model;
2
3 import java.util.List;
4
5 public class Dept {
6 private int deptid;
7 private String deptname;
8 private List<User> users;
9
10 public Dept() {
11 super();
12 // TODO Auto-generated constructor stub
13 }
14
15 public Dept(int deptid, String deptname, List<User> users) {
16 super();
17 this.deptid = deptid;
18 this.deptname = deptname;
19 this.users = users;
20 }
21
22 public int getDeptid() {
23 return deptid;
24 }
25 public void setDeptid(int deptid) {
26 this.deptid = deptid;
27 }
28 public String getDeptname() {
29 return deptname;
30 }
31 public void setDeptname(String deptname) {
32 this.deptname = deptname;
33 }
34
35 public List<User> getUsers() {
36 return users;
37 }
38
39 public void setUsers(List<User> users) {
40 this.users = users;
41 }
42
43 @Override
44 public String toString() {
45 return "Dept [deptid=" + deptid + ", deptname=" + deptname + ", users人數=" + users.size() + "]";
46 }
47
48 }
配置檔案:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.xsd">
6
7 <bean id="user1" class="com.model.User">
8 <property name="username" value="苦海"></property>
9 <property name="password" value="111"></property>
10 <property name="dept" ref="dept1"></property>
11
12 </bean>
13
14 <bean id="dept1" class="com.model.Dept">
15 <property name="deptid" value="6001"></property>
16 <property name="deptname" value="部門1"></property>
17 <property name="users">
18 <list>
19 <ref bean="user1"/>
20 </list>
21 </property>
22 </bean>
23
24 </beans>
測試:
1 package com.test;
2
3 import org.springframework.context.ApplicationContext;
4 import org.springframework.context.support.ClassPathXmlApplicationContext;
5
6 import com.model.Dept;
7 import com.model.User;
8
9 public class Test {
10 public static void main(String[] args) {
11 ApplicationContext ac=new ClassPathXmlApplicationContext("Spring-all.xml");//呼叫此方法時類已經例項化好了
12
13 User u=(User)ac.getBean("user1");//拿到例項化的類
14 Dept d=(Dept)ac.getBean("dept1");
15
16 System.out.println(u);
17 System.out.println(d);
18 ((ClassPathXmlApplicationContext)ac).close();
19
20 }
21 }
4, AutoWired(byType, byName)
autowire
自動裝載:
byName根據名字自動注入
user1的bean中並沒有dept屬性,但是還是打印出了這個屬性,因為它會找到這個類,然後在配置檔案中找到和該屬性同名的id,並自動注入
1 <bean id="user1" class="com.model.User" autowire="byName">
2 <property name="username" value="苦海"></property>
3 <property name="password" value="111"></property>
4 </bean>
5
6 <bean id="dept" lazy-init="true" class="com.model.Dept" init-method="init" destroy-method="destory" >
7 <property name="deptid" value="6001"></property>
8 <property name="deptname" value="部門1"></property>
9 <property name="users">
10 <list>
11 <ref bean="user1"/>
12 </list>
13 </property>
14 </bean>
1 ApplicationContext ac=new ClassPathXmlApplicationContext("Spring-all.xml");//呼叫此方法時類已經例項化好了
2 User u=(User)ac.getBean("user1");//拿到例項化的類
3 System.out.println(u);
4 ((ClassPathXmlApplicationContext)ac).close();
byType根據型別自動裝載,用法一致
需要注意,如果根據型別自動裝載,應只有一個該型別,否則會無發找到,報錯
autowire預設default,指的是根據<beans>宣告中得來選擇方法
5, scope, lazy-init, init-method, destroy-method(相當的不重要) scope="singleton(單例) / prototype(原型)"
預設情況下Spring中定義的Bean是以單例模式建立的。 在GoF中的單例模式是指一個ClassLoader中只存在類一個例項。 而在Spring中的單例實際上更確切的說應該是: 1.每個Spring Container中定義的Bean只存在一個例項 2.每個Bean定義只存在一個例項。
1 <bean id="user1" class="com.model.User" scope="singleton">
2 <property name="username" value="苦海"></property>
3 <property name="password" value="111"></property>
4 </bean>
1 ApplicationContext ac=new ClassPathXmlApplicationContext("Spring-all.xml");//呼叫此方法時類已經例項化好了
2 User u=(User)ac.getBean("user1");//拿到例項化的類
3 User u2=(User)ac.getBean("user1");
4 System.out.println(u==u2);
5 ((ClassPathXmlApplicationContext)ac).close();
1 <bean id="user1" class="com.model.User" scope="prototype">
2 <property name="username" value="苦海"></property>
3 <property name="password" value="111"></property>
4 </bean>
1 ApplicationContext ac=new ClassPathXmlApplicationContext("Spring-all.xml");
2 User u=(User)ac.getBean("user1");
3 User u2=(User)ac.getBean("user1");
4 System.out.println(u==u2);
5 ((ClassPathXmlApplicationContext)ac).close();
lazy-init="true" // 延遲載入,未生效
1 <bean id="dept1" lazy-init="true" class="com.model.Dept" init-method="init" destroy-method="destory" >
寫在beans中,設定全域性延遲載入
1 default-lazy-init="true"
lazy-init (一開始不初始化,用到的時候才初始化)
init-method="init" destory-method="destory" 不要和prototype一起使用
類被初始化的時候呼叫init,被消亡的時候呼叫destory
正常執行的結果只有一個init和destroy,雖然兩個service例項化,但是預設是單例,加了scope=prototype就執行不正常了,結果兩個init,沒有destroy,原因未知。 首先我們應該知道: 一、spring Bean的作用域:scope=singleton(預設,單例,生成一個例項) 二、spring Bean的作用域:scope=prototype(多執行緒, 生成多個例項) 三、單例模式,預設在程式初始化的時候例項化(lazy-init=”false”) 四、prototype,getBean的時候才是例項化 五、lazy-init 只對單例模式起作用,對 prototype 不起作用(因為 prototype 預設就不是程式初始化的時候例項化的)