1. 程式人生 > 其它 >Spring框架(二)反射機制, 注入, 單例模式, 自動裝載, 延遲載入

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 預設就不是程式初始化的時候例項化的)