本文主要介紹Spring中, 1 Bean 的 init-method 和 destroy-method 2 集合類型的裝配 3 註解方式裝配 4 以自動掃描把組件納入spring容器中管理 5 代理模式 一、Bean 的 init-method 和 destroy-method 以前在學Servl ...
本文主要介紹Spring中,
1 Bean 的 init-method 和 destroy-method
2 集合類型的裝配
3 註解方式裝配
4 以自動掃描把組件納入spring容器中管理
5 代理模式
一、Bean 的 init-method 和 destroy-method
以前在學Servlet的時候,有 init 和 destory 等時機,用Spring管理的bean 也可以有類似的時機,對於單實例的Bean ,在創建的時候會調用 initAAA() 方法,在銷毀的時候,會調用 destroyAAA()。
<bean name="userAction_name" class="cat.action.UserAction" init-method="initAAA" destroy-method="destroyAAA" >
public class UserAction { public void initAAA(){ System.out.println("initAAA調用了,這是在初始的時候調用的"); } public void destroyAAA(){ System.out.println("destroyAAA調用了,這是在銷毀的時候調用的"); } }
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); //會調用 initAAA() ctx.getBean("userAction_name"); ctx.close(); //銷毀容器 會調用destroyAAA()
//對於多實例的bean <bean name="userAction_name" class="cat.action.UserAction" init-method="initAAA" destroy-method="destroyAAA" scope ="prototype" > ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); ctx.getBean("userAction_name"); //調用 initAAA() ctx.close(); //銷毀容器 不會會調用destroyAAA() //因為對多實例的bean spring 在創建之後,就不再對它的生命周期負責
二、集合類型的配置
1)Set集合
public class UserAction { private Set<String> mySet ; //由Spring把這個集合的內容註進來 public void execute(){ for(String s:mySet){ System.out.println(s); } } public void setMySet(Set<String> mySet) { this.mySet = mySet; } } //配置文件 <bean name="userAction_name" class="cat.action.UserAction" > <property name="mySet"> <set> <value>李白</value> <value>唐太宗</value> <value>小杜</value> </set> </property>
2)List 集合
//和Set完全相同 只不過是上面的中的 set 要完全改成 list <set> <value>李白</value> <value>唐太宗</value> <value>小杜</value> </set>
3) Properties 集合
public class UserAction { private Properties myProps; //不要忘了生成set方法 public void execute(){ Set<String> keySet= myProps.stringPropertyNames(); Iterator<String> it=keySet.iterator(); while(it.hasNext()){ String key=it.next(); System.out.println(key+":"+myProps.getProperty(key)); } } ... }
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="myProps">
<props>
<prop key="key1">夏天</prop>
<prop key="key2">秋天</prop>
<prop key="key3">冬天</prop>
<prop key="key4">春天</prop>
</props>
</property>
</bean>
4) map集合
public class UserAction { private Map<String,String> myMap; //要生成set 方法 public void execute(){ Set<Map.Entry<String, String>> entrySet = myMap.entrySet(); Iterator<Map.Entry<String, String>> it= entrySet.iterator(); while(it.hasNext()){ Map.Entry<String, String > item= it.next(); System.out.println(item.getKey()+":"+item.getValue()); } }
<bean name="userAction_name" class="cat.action.UserAction" >
<property name="myMap">
<map>
<entry key="m_1" value="AK-47"></entry>
<entry key="m_2" value="M_16"></entry>
<entry key="m_3" value="M_P5"></entry>
</map>
</property>
</bean>
三、註解方式裝配
附 : p 這個名稱空間的作用就是簡化屬性的編寫
<bean name="userInfo" class="cat.beans.UserInfo" >
<property name="id" value="1"></property>
<property name="userName" value="趙強"></property>
<property name="password" value="admin"></property>
<property name="note" value="這是備註"></property>
</bean>
上面的等價於:
<bean name="userInfo" class="cat.beans.UserInfo" p:id="1" p:userName="趙強" p:note="這是備註" p:password="admin123" > </bean>
1) 引入jar包 common-annotations.jar
2) 引用入名稱空間 context
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" //這是引入的名稱空間 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
//上面這個是名稱空間所對應的xsd文件的路徑 <context:annotation-config /> //把Spring 對註解的處理器註冊到Spring中 <bean name="userAction_name" class="cat.action.UserAction" /> <bean name="userDao_name" class="cat.dao.UserDaoImpl" /> </beans>
public class UserAction { @Resource //用這個註解,進行註入 private IUserDao dao; public void execute(){ dao.addUser(); dao.updateUser(); } }
說明:
1.@Resource 是 javax.annotation.Resource 包下的
2.@Resource 預設是按名稱進行裝配,再按類型進行裝配(在不指定名稱的情況下),如果指定了名稱.它就嚴格的按名稱進行裝配
3.這個註解也可以寫在set方法上
//下麵的例子,使用了名稱 public class UserAction { @Resource(name="xxxxxx_dao") private IUserDao dao; public void execute(){ dao.addUser(); dao.updateUser(); } }
<bean name="userAction_name" class="cat.action.UserAction" /> <bean name="xxxxxx_dao" class="cat.dao.UserDaoImpl" /> //它會被註入 <bean name="oracleDao" class="cat.dao.UserDaoOracleImpl" />
4.@Autowired 註解和 @Resource 功能類似,它是在 org.springframework.beans.factory.annotation.Autowired 預設是按類型裝配 ,預設情況下,它要求依賴對象必須存在 ,如果對象是null 值 ,可以設置它的 required=false ,如果也想按名稱裝配 ,要和另一個註解一起使用
//例子 使用 @Autowired public class UserAction { @Autowired(required=false) @Qualifier("oracleDao") private IUserDao dao; //沒有給它生成get 和 set 方法 public void execute(){ dao.addUser(); dao.updateUser(); } }
四、以自動掃描把組件納入spring容器中管理
開啟自動掃描的方式
<context:component-scan base-package="cat.beans" /> <context:component-scan base-package="cat.dao" /> //如果用這種方式開啟了自動掃描,就不用加 <context:annotation-config />
它會自動在包下查找類 並納入Spring管理,包擴子包。它會自動找 帶有 @Service @Controller @Repository @Component 的類
==@Service 用於業務層
==@Controller 用於控制層
==@Repository 用於數據訪問層
==@Component 用於其他
目前只是一種規範,實際上用哪個都可以
說明:
1) 可以指定bean的名稱
@Controller("userAction_name") //傳參,指定名稱 public class UserAction { ... }
2) 預設情況下,這樣配置的bean是單例的,如果是多例
@Controller("userAction_name") @Scope("prototype") public class UserAction { }
//例子 控制層 @Controller("userAction_name") @Scope("prototype") public class UserAction { @Resource(name="userDaoOracleImpl") private IUserDao dao; public void execute(){ dao.addUser(); dao.delUser(); } } //數據訪問層 @Repository public class UserDaoOracleImpl implements IUserDao { public void addUser() { System.out.println("addUser方法被調用了Oracle版的 "); } public void delUser() { System.out.println("delUser方法被調用了Oracle版的 "); } public void updateUser() { System.out.println("updateUser方法被調用了Oracle版的 "); } } //測試 ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); UserAction action =(UserAction) ctx.getBean("userAction_name"); action.execute(); //對於納入自動掃描的bean ,它的名稱預設是類名, 首字母小寫
註意:使用了註解方式以後,原來的初始化和銷毀方法應該怎麼配置呢?
@Component @Scope("prototype") public class UserAction { ... @PostConstruct //初始方法 public void initAAA(){ System.out.println("初始化的方法被調用了"); } @PreDestroy //銷毀方法 public void destoryAAA(){ System.out.println("銷毀的方法被調用了"); }
五、代理模式
因為某個對象消耗太多資源,而且你的代碼並不是每個邏輯路徑都需要此對象, 你曾有過延遲創建對象的想法嗎?
你有想過限制訪問某個對象,也就是說,提供一組方法給普通用戶, 特別方法給管理員用戶?以上兩種需求都非常類似,並且都需要解決一個更大的問題:你如何提供一致的介面給某個對象讓它可以改變其內部功能,或者是從來不存在的功能? 可以通過引入一個新的對象,來實現對真實對象的操作或者將新的對象作為真實對象的一個替身。即代理對象。它可以在客戶端和目標對象之間起到中介的作用,並且可以通過代理對象去掉客戶不能看到的內容和服務或者添加客戶需要的額外服務。
業務類只需要關註業務邏輯本身,保證了業務類的重用性。這是代理的共有優點
靜態代理
由程式員創建或工具生成代理類的源碼,再編譯代理類。所謂靜態也就是在程式運行前,就已經存在代理類的位元組碼文件,代理類和委托類的關係在運行前就確定了。
//1) 介面 public interface IUserDao { void addUser(); void delUser(); void updateUser(); void searchUser(); } //2) 實現類 //委托類 public class UserDaoImpl implements IUserDao{ public void addUser() { System.out.println("addUser方法執行了"); } public void delUser() { System.out.println("delUser方法執行了"); } public void updateUser() { System.out.println("updateUser方法執行了"); } public void searchUser() { System.out.println("searchUser方法執行了"); } }
//3) 代理類 public class UserDaoProxy implements IUserDao { private UserDaoImpl userDaoImpl=new UserDaoImpl(); //代理類中,要有一個被委托的類的實例對象 private String path="log.txt"; public void addUser() { try { userDaoImpl.addUser(); BufferedWriter bw=new BufferedWriter(new FileWriter(path)); bw.write(new Date()+": 執行了添加用戶操作 "); bw.newLine(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } public void delUser() { try { userDaoImpl.delUser(); BufferedWriter bw=new BufferedWriter(new FileWriter(path)); bw.write(new Date()+": 執行了刪除用戶操作 "); bw.newLine(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } public void updateUser() { try { userDaoImpl.updateUser(); BufferedWriter bw=new BufferedWriter(new FileWriter(path)); bw.write(new Date()+": 執行了更新用戶操作 "); bw.newLine(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } public void searchUser() { long begin=System.currentTimeMillis(); userDaoImpl.searchUser(); long end=System.currentTimeMillis(); System.out.println("查詢用戶一共用了:" +(end-begin) +"ms"); } }
//3) 代理工廠 public class static UserDaoProxyFactory { public IUserDao getUserDao(){ return new UserDaoProxy(); } }
//4) 測試 public static void main(String[] args) { IUserDao dao=UserDaoProxyFactory.getUserDao(); dao.addUser(); dao.updateUser(); dao.delUser(); dao.searchUser(); }
靜態代理的缺點:
1)代理對象的一個介面只服務於一種類型的對象,如果要代理的方法很多,勢必要為每一種方法都進行代理,靜態代理在程式規模稍大時就無法勝任了。
2)如果介面增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法。增加了代碼維護的複雜度。