Eclipse 快捷鍵大全
類別 命令 鍵序列 說明
C/C++ Source Add Block Comment Ctrl+Shift+/ C/C++ Editor
C/C++ Source Add Include Ctrl+Shift+N C/C++ Editor
C/C++ Source Comment Ctrl+/ C/C++ Editor
C/C++ Source Find Declaration Ctrl+G C/C++ Editor
C/C++ Source Find References Ctrl+Shift+G C/C++ Editor
C/C++ Source Format Ctrl+Shift+F C/C++ Editor
C/C++ Source Go to Matching Bracket Ctrl+Shift+P C/C++ Editor
C/C++ Source Go to next C/C++ member Ctrl+Shift+向下鍵 C/C++ Editor
C/C++ Source Go to previous C/C++ member Ctrl+Shift+向上鍵 C/C++ Editor
C/C++ Source Open Declaration F3 C/C++ Editor
C/C++ Source Open Definition Ctrl+F3 C/C++ Editor
C/C++ Source Open Type Ctrl+Shift+T C/C++ Editor
C/C++ Source Remove Block Comment Ctrl+Shift+\ C/C++ Editor
C/C++ Source Show outline Ctrl+O C/C++ Editor
C/C++ Source Uncomment Ctrl+\ C/C++ Editor
Makefile Source Comment Ctrl+/ Makefile Editor
Makefile Source Open declaration F3 Makefile Editor
Makefile Source Uncomment Ctrl+\ Makefile Editor
Refactor - C/C++ Redo - Refactoring Alt+Shift+Y C/C++ Editor
Refactor - C/C++ Rename - Refactoring Alt+Shift+R C/C++ Editor
Refactor - C/C++ Undo - Refactoring Alt+Shift+Z C/C++ Editor
View Zoom In Ctrl+= 在窗口中
View Zoom Out Ctrl+- 在窗口中
搜索 工作空間中的聲明 Ctrl+G 在窗口中
搜索 工作空間中的引用 Ctrl+Shift+G 在窗口中
搜索 打開“搜索”對話框 Ctrl+H 在窗口中
搜索 顯示“文件中的出現位置”快速菜單 Ctrl+Shift+U 在窗口中
文件 “新建”菜單 Alt+Shift+N 在窗口中
文件 保存 Ctrl+S 在窗口中
文件 全部保存 Ctrl+Shift+S 在窗口中
文件 全部關閉 Ctrl+Shift+F4 在窗口中
文件 全部關閉 Ctrl+Shift+W 在窗口中
文件 關閉 Ctrl+F4 在窗口中
文件 關閉 Ctrl+W 在窗口中
文件 刷新 F5 在窗口中
文件 屬性 Alt+Enter 在窗口中
文件 打印 Ctrl+P 在窗口中
文件 新建 Ctrl+N 在窗口中
文件 重命名 F2 在窗口中
文本編輯 上一個詞語 Ctrl+左箭頭 編輯文本
文本編輯 上滾行 Ctrl+向上鍵 編輯文本
文本編輯 下一個詞語 Ctrl+右箭頭 編輯文本
文本編輯 下滾行 Ctrl+向下鍵 編輯文本
文本編輯 全部展開 Ctrl+Numpad_Multiply 編輯文本
文本編輯 切換折疊 Ctrl+Numpad_Divide 編輯文本
文本編輯 刪除上一個詞語 Ctrl+Backspace 編輯文本
文本編輯 刪除下一個詞語 Ctrl+Delete 編輯文本
文本編輯 刪除至行末 Ctrl+Shift+Delete 編輯文本
文本編輯 刪除行 Ctrl+D 編輯文本
文本編輯 在當前行上面插入行 Ctrl+Shift+Enter 編輯文本
文本編輯 在當前行下面插入行 Shift+Enter 編輯文本
文本編輯 復制行 Ctrl+Alt+向下鍵 編輯文本
文本編輯 將行上移 Alt+向上鍵 編輯文本
文本編輯 將行下移 Alt+向下鍵 編輯文本
文本編輯 展開 Ctrl+Numpad_Add 編輯文本
文本編輯 折疊 Ctrl+Numpad_Subtract 編輯文本
文本編輯 改寫切換 Insert 編輯文本
文本編輯 更改為大寫 Ctrl+Shift+X 編輯文本
文本編輯 更改為小寫 Ctrl+Shift+Y 編輯文本
文本編輯 選擇上一個詞語 Ctrl+Shift+左箭頭 編輯文本
文本編輯 選擇下一個詞語 Ctrl+Shift+右箭頭 編輯文本
文本編輯 重復行 Ctrl+Alt+向上鍵 編輯文本
查看 Java 包資源管理器 Alt+Shift+Q,P 在窗口中
查看 Java 聲明 Alt+Shift+Q,D 在窗口中
查看 Java 類型層次結構 Alt+Shift+Q,T 在窗口中
查看 Javadoc Alt+Shift+Q,J 在窗口中
查看 變量 Alt+Shift+Q,V 在窗口中
查看 同步 Alt+Shift+Q,Y 在窗口中
查看 備忘單 Alt+Shift+Q,H 在窗口中
查看 控制臺 Alt+Shift+Q,C 在窗口中
查看 搜索 Alt+Shift+Q,S 在窗口中
查看 斷點 Alt+Shift+Q,B 在窗口中
查看 顯示視圖 (查看: 大綱) Alt+Shift+Q,O 在窗口中
查看 顯示視圖 (查看: 問題) Alt+Shift+Q,X 在窗口中
瀏覽 &Quick Cross References Alt+Shift+P 編輯 Java 源代碼
瀏覽 Open AspectJ Type Alt+Shift+A 在窗口中
瀏覽 Open AspectJ Type in Hierarchy Alt+Shift+H 在窗口中
瀏覽 “顯示位置”菜單 Alt+Shift+W 在窗口中
瀏覽 上一個編輯位置 Ctrl+Q 在窗口中
瀏覽 下一頁 Ctrl+. 在窗口中
瀏覽 前一頁 Ctrl+, 在窗口中
瀏覽 前移歷史記錄 Alt+右箭頭 在窗口中
瀏覽 后退歷史記錄 Alt+左箭頭 在窗口中
瀏覽 在層次結構中打開類型 Ctrl+Shift+H 在窗口中
瀏覽 快速大綱 Ctrl+O 編輯 Java 源代碼
瀏覽 快速層次結構 Ctrl+T 編輯 Java 源代碼
瀏覽 打開聲明 F3 在窗口中
瀏覽 打開外部 Javadoc Shift+F2 在窗口中
瀏覽 打開類型 Ctrl+Shift+T 在窗口中
瀏覽 打開類型層次結構 F4 在窗口中
瀏覽 打開結構 Ctrl+F3 編輯 Java 源代碼
瀏覽 打開調用層次結構 Ctrl+Alt+H 在窗口中
瀏覽 打開資源 Ctrl+Shift+R 在窗口中
瀏覽 轉至上一個成員 Ctrl+Shift+向上鍵 編輯 Java 源代碼
瀏覽 轉至下一個成員 Ctrl+Shift+向下鍵 編輯 Java 源代碼
瀏覽 轉至匹配的方括號 Ctrl+Shift+P 編輯 Java 源代碼
瀏覽 轉至行 Ctrl+L 編輯文本
源代碼 切換 Ant 標記出現 Alt+Shift+O 編輯 Ant 構建文件
源代碼 切換標記出現 Alt+Shift+O 編輯 Java 源代碼
源代碼 切換注釋 Ctrl+/ 編輯 Java 源代碼
源代碼 切換注釋 Ctrl+7 編輯 Java 源代碼
源代碼 切換注釋 Ctrl+Shift+C 編輯 Java 源代碼
源代碼 在文件中重命名 Alt+Shift+R 編輯 Ant 構建文件
源代碼 快速輔助 - 在文件中重命名 Ctrl+2,R 編輯 Java 源代碼
源代碼 快速輔助 - 指定給字段 Ctrl+2,F 編輯 Java 源代碼
源代碼 快速輔助 - 指定給局部變量 Ctrl+2,L 編輯 Java 源代碼
源代碼 打開外部文檔 Shift+F2 編輯 Ant 構建文件
源代碼 顯示工具提示描述 F2 編輯 Ant 構建文件
源代碼 顯示源代碼快速菜單 Alt+Shift+S 在窗口中
源代碼 格式 Ctrl+Shift+F 編輯 Ant 構建文件
源代碼 格式化 Ctrl+Shift+F 編輯 Java 源代碼
源代碼 添加 Javadoc 注釋 Alt+Shift+J 在窗口中
源代碼 添加塊注釋 Ctrl+Shift+/ 編輯 Java 源代碼
源代碼 添加導入 Ctrl+Shift+M 編輯 Java 源代碼
源代碼 組織導入 Ctrl+Shift+O 在窗口中
源代碼 縮進行 Ctrl+I 編輯 Java 源代碼
源代碼 除去出現注釋 Alt+Shift+U 編輯 Java 源代碼
源代碼 除去塊注釋 Ctrl+Shift+\ 編輯 Java 源代碼
窗口 上一個編輯器 Ctrl+Shift+F6 在窗口中
窗口 上一個視圖 Ctrl+Shift+F7 在窗口中
窗口 上一個透視圖 Ctrl+Shift+F8 在窗口中
窗口 下一個編輯器 Ctrl+F6 在窗口中
窗口 下一個視圖 Ctrl+F7 在窗口中
窗口 下一個透視圖 Ctrl+F8 在窗口中
窗口 切換至編輯器 Ctrl+Shift+E 在窗口中
窗口 將活動視圖或編輯器最大化 Ctrl+M 在窗口中
窗口 打開編輯器下拉列表 Ctrl+E 在窗口中
窗口 顯示標尺上下文菜單 Ctrl+F10 編輯文本
窗口 顯示系統菜單 Alt+- 在窗口中
窗口 顯示視圖菜單 Ctrl+F10 在窗口中
窗口 顯示鍵輔助 Ctrl+Shift+L 在對話框和窗口中
窗口 激活編輯器 F12 在窗口中
編輯 Add Block Comment Ctrl+Shift+/ Editing in Structured Text Editors
編輯 Format Active Elements Ctrl+I Editing in Structured Text Editors
編輯 Format Document Ctrl+Shift+F Editing in Structured Text Editors
編輯 Move Alt+Shift+V Editing JSP Source
編輯 Occurrences in File Ctrl+Shift+A Editing in Structured Text Editors
編輯 Open Selection F3 Editing in Structured Text Editors
編輯 Quick Fix Ctrl+1 Editing in Structured Text Editors
編輯 Remove Block Comment Ctrl+Shift+\ Editing in Structured Text Editors
編輯 Rename Alt+Shift+R Editing JSP Source
編輯 Rename XSD element Alt+Shift+R Editing XSD context
編輯 Restore Last Selection Alt+Shift+向下鍵 Editing in Structured Text Editors
編輯 Select Enclosing Element Alt+Shift+向上鍵 Editing in Structured Text Editors
編輯 Select Next Element Alt+Shift+右箭頭 Editing in Structured Text Editors
編輯 Select Previous Element Alt+Shift+左箭頭 Editing in Structured Text Editors
編輯 Show Tooltip Description F2 Editing in Structured Text Editors
編輯 Toggle Comment Ctrl+Shift+C Editing in Structured Text Editors
編輯 “快速差別”開關 Ctrl+Shift+Q 編輯文本
編輯 上下文信息 Alt+? 在窗口中
編輯 上下文信息 Alt+Shift+? 在窗口中
編輯 內容輔助 Alt+/ 在對話框和窗口中
編輯 切換插入方式 Ctrl+Shift+Insert 編輯文本
編輯 刪除 Delete 在窗口中
編輯 剪切 Ctrl+X 在對話框和窗口中
編輯 剪切 Shift+Delete 在對話框和窗口中
編輯 增量查找 Ctrl+J 編輯文本
編輯 增量逆向查找 Ctrl+Shift+J 編輯文本
編輯 復制 Ctrl+C 在對話框和窗口中
編輯 復制 Ctrl+Insert 在對話框和窗口中
編輯 復原上一個選擇 Alt+Shift+向下鍵 編輯 Java 源代碼
編輯 快速修正 Ctrl+1 在窗口中
編輯 撤消 Ctrl+Z 在窗口中
編輯 文字補全 Ctrl+Alt+/ 編輯文本
編輯 顯示工具提示描述 F2 編輯 Java 源代碼
編輯 查找上一個 Ctrl+Shift+K 編輯文本
編輯 查找下一個 Ctrl+K 編輯文本
編輯 查找并替換 Ctrl+F 在窗口中
編輯 粘貼 Ctrl+V 在對話框和窗口中
編輯 粘貼 Shift+Insert 在對話框和窗口中
編輯 選擇上一個元素 Alt+Shift+左箭頭 編輯 Java 源代碼
編輯 選擇下一個元素 Alt+Shift+右箭頭 編輯 Java 源代碼
編輯 選擇全部 Ctrl+A 在對話框和窗口中
編輯 選擇外層元素 Alt+Shift+向上鍵 編輯 Java 源代碼
編輯 重做 Ctrl+Y 在窗口中
運行/調試 Debug AspectJ/Java Application Alt+Shift+D,C 在窗口中
運行/調試 Debug on Server Alt+Shift+D,R 在窗口中
運行/調試 EOF Ctrl+Z 在控制臺中
運行/調試 Profile on Server Alt+Shift+P,R 在窗口中
運行/調試 Run AspectJ/Java Application Alt+Shift+X,C 在窗口中
運行/調試 Run on Server Alt+Shift+X,R 在窗口中
運行/調試 切換單步執行過濾器 Shift+F5 在窗口中
運行/調試 切換行斷點 Ctrl+Shift+B 在窗口中
運行/調試 單步跳入 F5 調試
運行/調試 單步跳入選擇的內容 Ctrl+F5 調試
運行/調試 單步跳過 F6 調試
運行/調試 單步返回 F7 調試
運行/調試 執行 Ctrl+U 在窗口中
運行/調試 顯示 Ctrl+Shift+D 在對話框和窗口中
運行/調試 檢查 Ctrl+Shift+I 在對話框和窗口中
運行/調試 繼續 F8 調試
運行/調試 調試 Ant 構建 Alt+Shift+D,Q 在窗口中
運行/調試 調試 Eclipse 應用程序 Alt+Shift+D,E 在窗口中
運行/調試 調試 JUnit 插件測試 Alt+Shift+D,P 在窗口中
運行/調試 調試 JUnit 測試 Alt+Shift+D,T 在窗口中
運行/調試 調試 Java Applet Alt+Shift+D,A 在窗口中
運行/調試 調試 Java 應用程序 Alt+Shift+D,J 在窗口中
運行/調試 調試 SWT 應用程序 Alt+Shift+D,S 在窗口中
運行/調試 調試上次啟動 F11 在窗口中
運行/調試 運行 Ant 構建 Alt+Shift+X,Q 在窗口中
運行/調試 運行 Eclipse 應用程序 Alt+Shift+X,E 在窗口中
運行/調試 運行 JUnit 插件測試 Alt+Shift+X,P 在窗口中
運行/調試 運行 JUnit 測試 Alt+Shift+X,T 在窗口中
運行/調試 運行 Java Applet Alt+Shift+X,A 在窗口中
運行/調試 運行 Java 應用程序 Alt+Shift+X,J 在窗口中
運行/調試 運行 SWT 應用程序 Alt+Shift+X,S 在窗口中
運行/調試 運行上次啟動 Ctrl+F11 在窗口中
運行/調試 運行至行 Ctrl+R 調試
重構 - Java 內聯 Alt+Shift+I 在窗口中
重構 - Java 將局部變量轉換為字段 Alt+Shift+F 編輯 Java 源代碼
重構 - Java 抽取局部變量 Alt+Shift+L 在窗口中
重構 - Java 抽取方法 Alt+Shift+M 在窗口中
重構 - Java 撤銷 - 重構 Alt+Shift+Z 在窗口中
重構 - Java 顯示重構快速菜單 Alt+Shift+T 在窗口中
重構 - Java 更改方法特征符 Alt+Shift+C 在窗口中
重構 - Java 移動 - 重構 Alt+Shift+V 在窗口中
重構 - Java 重做 - 重構 Alt+Shift+Y 在窗口中
重構 - Java 重命名 - 重構 Alt+Shift+R 在窗口中
項目 全部構建 Ctrl+B 在窗口中
java代碼:? |
public class ExampleBean { ? ? private BeanOne beanOne; ? ? private BeanTwo beanTwo; ? ? privateint count; ? ? ? ? publicvoid setBeanOne(BeanOne beanOne){ ? ? ? ? this.beanOne = beanOne; ? ? } ? ? ? ? publicvoid setBeanTwo(BeanTwo beanTwo){ ? ? ? ? this.beanTwo = beanTwo; ? ? } ? ? ? ? publicvoid setCount(int count){ ? ? ? ? this.count = count; ? ? }? ? } |
java代碼:? |
<bean id="exampleBean" class="examples.ExampleBean"> ? ? <property name="beanOne"><ref bean="bean1"/></property> ? ? <property name="beanTwo"><ref bean="bean2"/></property> ? ? <property name="count"><value>1</value></property> </bean> <bean id="bean1" class="examples.BeanOne"/> <bean id="bean2" class="examples.BeanTwo"/> |
java代碼:? |
public class ExampleBean { ? ? private BeanOne beanOne; ? ? private BeanTwo beanTwo; ? ? privateint count; ? ? ? ? public ExampleBean(BeanOne beanOne, BeanTwo beanTwo, int count){ ? ? ? ? this.beanOne = beanOne; ? ? ? ? this.beanTwo = beanTwo; ? ? ? ? this.count = count; ? ? } } |
java代碼:? |
<bean id="exampleBean" class="examples.ExampleBean"> ? ? <constructor-arg><ref bean="bean1"/></constructor-arg> ? ? <constructor-arg><ref bean="bean2"/></constructor-arg> ? ? <constructor-arg><value>1</value></constructor-arg> </bean> <bean id="bean1" class="examples.BeanOne"/> <bean id="bean2" class="examples.BeanTwo"/> |
java代碼:? |
public class ExampleBean { ? ? private BeanOne beanOne; ? ? private BeanTwo beanTwo; ? ? privateint count; ? ? //構造函數私有 ? ? private ExampleBean(BeanOne beanOne, BeanTwo beanTwo, int count){ ? ? ? ? this.beanOne = beanOne; ? ? ? ? this.beanTwo = beanTwo; ? ? ? ? this.count = count; ? ? } ? ? //對外提供靜態的方法 ? ? publicstatic ExampleBean createInstance(BeanOne beanOne, BeanTwo beanTwo, int count){ ? ? ? ? ExampleBean eb = new ExampleBean(beanOne,beanTwo,count); ? ? ? ? return eb; ? ? } } |
java代碼:? |
<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance"> ? ? <constructor-arg><ref bean="bean1"/></constructor-arg> ? ? <constructor-arg><ref bean="bean2"/></constructor-arg> ? ? <constructor-arg><value>1</value></constructor-arg> </bean> <bean id="bean1" class="examples.BeanOne"/> <bean id="bean2" class="examples.BeanTwo"/> |
java代碼:? |
<bean id="exampleBean" ? ? ? factory-bean="myFactoryBean" ? ? ? factory-method="createInstance"/> <bean id="myFactoryBean" class="examples.ExampleBean" factory-method="createInstance"> ? ? <constructor-arg><ref bean="bean1"/></constructor-arg> ? ? <constructor-arg><ref bean="bean2"/></constructor-arg> ? ? <constructor-arg><value>1</value></constructor-arg> </bean> <bean id="bean1" class="examples.BeanOne"/> <bean id="bean2" class="examples.BeanTwo"/> |
java代碼:? |
<property name="driverClassName"> ? ? <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> ? ? <value>jdbc:mysql://localhost:3306/mydb</value> </property> |
java代碼:? |
<property name="email"><value></value></property> <property name="email"><null/></property> |
java代碼:? |
<property name="school"> ? ?<props> ? ? ? <prop key="school01">The xi'an technology university</prop> ? ? ? <prop key="school02">The BeiJing university</prop> ? ?</props> </property> <property name="someList"> ? ?<list> ? ? ? <value>a list element followed by a reference</value> ? ? ? <ref bean="myDataSource"/> ? ?</list> </property> <property name="someMap"> ? ?<map> ? ? ? <entry key="001"> ? ? ? ? ?<value>just some string</value> ? ? ? </entry> ? ? ? <entry key="yup a ref"> ? ? ? ? ?<ref bean="myDataSource"/> ? ? ? </entry> ? ?</map> </property> ? ? ? ? <property name="someSet"> ? ? ? <set> ? ? ? ? ?<value>just some string</value> ? ? ? ? ?<ref bean="myDataSource"/> ? ? ? </set> </property> |
java代碼:? |
<bean id="dep" class="com.bean.Conpany"> ? ? <property name="manager"> ? ? ? ? <bean class="com.bean.Person"> ? ? ? ? ? ? <property name="name"><value>Tony</value></property> ? ? ? ? ? ? <property name="age"><value>51</value></property> ? ? ? ? </bean> ? ? </property> </bean> |
java代碼:? |
<bean id="person_manger" class="com.bean.Person"> ? ? <property name="name"><value>Tony</value></property> ? ? <property name="age"><value>51</value></property> </bean> <bean id="dep" class="com.bean.Conpany"> ? ? <property name="manager"> ? ? ? ? <idref bean="person_manager"/> ? ? </property> </bean> |
java代碼:? |
<bean id="dep" class="com.bean.Conpany"> ? ? <property name="manager"> ? ? ? ? <bean class="com.bean.Person"> ? ? ? ? ? ? <property name="name"><value>Tony</value></property> ? ? ? ? ? ? <property name="age"><value>51</value></property> ? ? ? ? </bean> ? ? </property> </bean> |
java代碼:? |
<bean id="person_manger" class="com.bean.Person"> ? ? <property name="name"><value>Tony</value></property> ? ? <property name="age"><value>51</value></property> </bean> <bean id="dep" class="com.bean.Conpany"> ? ? <property name="manager"> ? ? ? ? <idref bean="person_manager"/> ? ? </property> </bean> |
這是好友面試的一道題,其實我知道使用的區別,StringBuffer必須new出來,StringBuffer的append的效率比string的+=的效率高,
其實發現還有很大的區別,看了看以前scjp的考題
public class Test {
?? public static void stringReplace (String text) {
?? text = text.replace('j' , 'i');
?? }
??
?? public static void bufferReplace (StringBuffer text) {
?? text = text.append("C");
?? }
??
??? public static void main (String args[]) {
??? String textString = new String ("java");
??? StringBuffer textBuffer = new StringBuffer ("java");
???
??? stringReplace (textString);
??? bufferReplace (textBuffer);
???
??? System.out.println (textString + textBuffer);
??? }
??? }
答案是 javajavaC
這是Java參數傳遞(by value)造成的,是不可變的(immutable).,例如 基本類型,String傳值,復制了值傳遞過去;可變的(Object)傳值,復制了引用傳遞過去。
而題目中第七行text = text.append (“C”),append方法會改變text中的值
而這個text與main中的textBuffer是指向同一個對象,所以對應的輸出是javac。
string的值永遠不會改變!
String a = "a";//假設a指向地址0x0001,
a = "b";//重新負值后a指向地址0x0002,但0x0001地址中保存的"a"依舊存在,但已經不再是a所指向的。
從表面上看String類型的對象改變了值,但事實是他不能改變值,只能改變指向的地址
StringBuffer則不同,直接改變指向的地址中保留的值
還有
StringBuffer s1 = new StringBuffer("a");
StringBuffer s2 = new StringBuffer("a");
s1.equals(s2)//為什么是false
String s1 = new String("a");
String s2 = new String("a");
s1.equals(s2)//為什么是true
StringBuffer類中沒有重新定義equals這個方法,因此這個方法就來自Object類,
而Object類中的equals方法是用來比較地址的,所以等于false.
String類中重新定義了equals這個方法,而且比較的是值,而不是地址。所以會是
true。
對于這樣能不能面試出真正的水平,感到懷疑。
代碼: |
package com.company.springaop.test; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class TestBeforeAdvice implements MethodBeforeAdvice { ? public void before(Method m, Object[] args, Object target) ? throws Throwable { ? ? System.out.println("Hello world! (by " ? ? ? ? + this.getClass().getName() ? ? ? ? + ")"); ? } } ? |
代碼: |
package com.company.springaop.test; public class BeanImpl implements Bean { ? public void theMethod() { ? ? System.out.println(this.getClass().getName() ? ? ? ? + "." + new Exception().getStackTrace()[0].getMethodName() ? ? ? ? + "()" ? ? ? ? + " says HELLO!"); ? } } |
代碼: |
package com.company.springaop.test; public interface Bean { ? public void theMethod(); } |
代碼: |
package com.company.springaop.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; public class Main { ? public static void main(String[] args) { ? ? //Read the configuration file ? ? ApplicationContext ctx ? ? ? ? = new FileSystemXmlApplicationContext("springconfig.xml"); ? ? //Instantiate an object ? ? Bean x = (Bean) ctx.getBean("bean"); ? ? //Execute the public method of the bean (the test) ? ? x.theMethod(); ? } } |
代碼: |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC? "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> ? <!--CONFIG--> ? <bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean"> ? ? <property name="proxyInterfaces"> ? ? ? <value>com.company.springaop.test.Bean</value> ? ? </property> ? ? <property name="target"> ? ? ? <ref local="beanTarget"/> ? ? </property> ? ? <property name="interceptorNames"> ? ? ? <list> ? ? ? ? <value>theAdvisor</value> ? ? ? </list> ? ? </property> ? </bean> ? <!--CLASS--> ? <bean id="beanTarget" class="com.company.springaop.test.BeanImpl"/> ? <!--ADVISOR--> ? <!--Note: An advisor assembles pointcut and advice--> ? <bean id="theAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> ? ? <property name="advice"> ? ? ? <ref local="theBeforeAdvice"/> ? ? </property> ? ? <property name="pattern"> ? ? ? <value>com\.company\.springaop\.test\.Bean\.theMethod</value> ? ? </property> ? </bean> ? <!--ADVICE--> ? <bean id="theBeforeAdvice" class="com.company.springaop.test.TestBeforeAdvice"/> </beans> ? |
前幾天接到了新的任務,開始了公司項目管理軟件的開發(復雜其中一部分).
這段時間開始由項目經理帶著我們開發,這幾天跟他學到的東西還是不少的.如果每天都能這樣
該多好呀.?? 而且意識到嚴謹的學習態度的重要性,不能囫圇吞棗.要學就要學通.
轉自:Potain 的BLOG
另外,你不愿意你的DAO測試代碼每次都打開關系Session,因此,我們一般會采用OpenSessionInView模式。
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, ?????? FilterChain filterChain) throws ServletException, IOException { ??????SessionFactory sessionFactory = lookupSessionFactory(); ??????logger.debug("Opening Hibernate Session in OpenSessionInViewFilter"); ??????Session session = getSession(sessionFactory); ??????TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); ??????try { ????????????filterChain.doFilter(request, response); ??????} ??????finally { ????????????TransactionSynchronizationManager.unbindResource(sessionFactory); ????????????logger.debug("Closing Hibernate Session in OpenSessionInViewFilter"); ????????????closeSession(session, sessionFactory); ??????} }
為什么綁定以后,就可以防止每次不會新開一個Session呢?看看HibernateDaoSupport的情況:
publicfinal void setSessionFactory(SessionFactory sessionFactory) { this.hibernateTemplate = new HibernateTemplate(sessionFactory); } protectedfinal HibernateTemplate getHibernateTemplate() { return hibernateTemplate; }
我們的DAO將使用這個template進行操作:
publicabstract class BaseHibernateObjectDao ??????extends HibernateDaoSupport ??????implements BaseObjectDao {??????protected BaseEntityObject getByClassId(finallong id) { ????????????BaseEntityObject obj = ??????????????????(BaseEntityObject) getHibernateTemplate() ????????????????????????.execute(new HibernateCallback() {
??????????????????publicObject doInHibernate(Session session) ????????????????????????throws HibernateException { ????????????????????????return session.get(getPersistentClass(), newLong(id)); ??????????????????}
????????????}); ????????????return obj; ??????}
??????public void save(BaseEntityObject entity) { ????????????getHibernateTemplate().saveOrUpdate(entity); ??????}
??????public void remove(BaseEntityObject entity) { ????????????try {
??????????????????getHibernateTemplate().delete(entity); ????????????} catch (Exception e) { ??????????????????thrownew FlexEnterpriseDataAccessException(e); ????????????} ??????}
??????public void refresh(final BaseEntityObject entity) { ????????????getHibernateTemplate().execute(new HibernateCallback() {
??????????????????publicObject doInHibernate(Session session) ????????????????????????throws HibernateException { ????????????????????????session.refresh(entity); ????????????????????????returnnull; ??????????????????}
????????????}); ??????}
??????public void replicate(finalObject entity) { ????????????getHibernateTemplate().execute(new HibernateCallback() {
??????????????????publicObject doInHibernate(Session session) ????????????????????????throws HibernateException { ????????????????????????session.replicate(entity, ReplicationMode.OVERWRITE); ????????????????????????returnnull; ??????????????????}
????????????}); ??????}
publicObject execute(HibernateCallback action) throws DataAccessException { ??????Session session = (!this.allowCreate ? ????????????SessionFactoryUtils.getSession(getSessionFactory(), false) : ????????????SessionFactoryUtils.getSession(getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator())); ??????boolean existingTransaction = TransactionSynchronizationManager.hasResource(getSessionFactory()); ??????if (!existingTransaction && getFlushMode() == FLUSH_NEVER) { ????????????session.setFlushMode(FlushMode.NEVER); ??????} ??????try { ????????????Object result = action.doInHibernate(session); ????????????flushIfNecessary(session, existingTransaction); ????????????return result; ??????} ??????catch (HibernateException ex) { ????????????throw convertHibernateAccessException(ex); ??????} ??????catch (SQLException ex) { ????????????throw convertJdbcAccessException(ex); ??????} ??????catch (RuntimeException ex) { ????????????// callback code threw application exception ????????????throw ex; ??????} ??????finally { ????????????SessionFactoryUtils.closeSessionIfNecessary( session, getSessionFactory()); ??????} }
publicstatic void closeSessionIfNecessary(Session session, SessionFactory sessionFactory) throws CleanupFailureDataAccessException { ??????if (session == null || ?????? TransactionSynchronizationManager.hasResource(sessionFactory)) { ????????????return; ??????} ??????logger.debug("Closing Hibernate session"); ??????try { ????????????session.close(); ??????} ??????catch (JDBCException ex) { ????????????// SQLException underneath ????????????thrownew CleanupFailureDataAccessException( ????????????"Cannot close Hibernate session", ex.getSQLException()); ??????} ??????catch (HibernateException ex) { ????????????thrownew CleanupFailureDataAccessException( ????????????"Cannot close Hibernate session", ex); ??????} }
使用同樣的方法,這兩個Interceptor可以用來解決問題。但是關鍵的不同之處在于,它們的力度只能定義在DAO或業務方法上,而不是在我們的Test方法上,除非我們把它們應用到TestCase的方法上,但你不大可能為TestCase去定義一個接口,然后把Interceptor應用到這個接口的某些方法上。直接使用HibernateTransactionManager也是一樣的。因此,如果我們有這樣的測試:
Category parentCategory = new Category (); ??????parentCategory.setName("parent"); ??????dao.save(parentCategory);??????Category childCategory = new Category(); childCategory.setName("child");
??????parentCategory.addChild(childCategory); ??????dao.save(childCategory);
??????Category savedParent = dao.getCategory("parent"); ??????Category savedChild = (Category ) savedParent.getChildren().get(0); ??????assertEquals(savedChild, childCategory);
一種方法是對TestCase應用Interceptor或者TransactionManager,但這個恐怕會造成很多麻煩。除非是使用增強方式的AOP.我前期采用這種方法(Aspectwerkz),在Eclipse里面也跑得含好。
另一種方法是在TestCase的setup和teardown里面實現和Filter完全一樣的處理,其他的TestCase都從這個TestCase繼承,這種方法是我目前所使用的。
轉自:Karl Baum's Weblog
Karl Baum's Weblog
All | General | Java
Thursday July 08, 2004
Lazy Initialization and the DAO pattern with Hibernate and Spring
Hibernate and Lazy Initialization
Hibernate object relational mapping offers both lazy and non-lazy modes of object initialization. Non-lazy initialization retrieves an object and all of its related objects at load time. This can result in hundreds if not thousands of select statements when retrieving one entity. The problem is compounded when bi-directional relationships are used, often causing entire databases to be loaded during the initial request. Of course one could tediously examine each object relationship and manually remove those most costly, but in the end, we may be losing the ease of use benefit sought in using the ORM tool.
The obvious solution is to employ the lazy loading mechanism provided by hibernate. This initialization strategy only loads an object's one-to-many and many-to-many relationships when these fields are accessed. The scenario is practically transparent to the developer and a minimum amount of database requests are made, resulting in major performance gains. One drawback to this technique is that lazy loading requires the Hibernate session to remain open while the data object is in use. This causes a major problem when trying to abstract the persistence layer via the Data Access Object pattern. In order to fully abstract the persistence mechanism, all database logic, including opening and closing sessions, must not be performed in the application layer. Most often, this logic is concealed behind the DAO implementation classes which implement interface stubs. The quick and dirty solution is to forget the DAO pattern and include database connection logic in the application layer. This works for small applications but in large systems this can prove to be a major design flaw, hindering application extensibility.
Being Lazy in the Web Layer
Fortunately for us, the Spring Framework has developed an out of box web solution for using the DAO pattern in combination with Hibernate lazy loading. For anyone not familiar with using the Spring Framework in combination with Hibernate, I will not go into the details here, but I encourage you to read Hibernate Data Access with the Spring Framework. In the case of a web application, Spring comes with both the OpenSessionInViewFilter and the OpenSessionInViewInterceptor. One can use either one interchangeably as both serve the same function. The only difference between the two is the interceptor runs within the Spring container and is configured within the web application context while the Filter runs in front of Spring and is configured within the web.xml. Regardless of which one is used, they both open the hibernate session during the request binding this session to the current thread. Once bound to the thread, the open hibernate session can transparently be used within the DAO implementation classes. The session will remain open for the view allowing lazy access the database value objects. Once the view logic is complete, the hibernate session is closed either in the Filter doFilter method or the Interceptor postHandle method. Below is an example of the configuration of each component:
Interceptor Configuration
<beans>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/>
</list>
</property>
<property name="mappings">
...
</bean>
...
<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
</beans>
Filter Configuration
<web-app>
...
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</filter-class>
</filter>
...
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.spring</url-pattern>
</filter-mapping>
...
</web-app>
Implementing the Hibernate DAO's to use the open session is simple. In fact, if you are already using the Spring Framework to implement your Hibernate DAO's, most likely you will not have to change a thing. The DAO's must access Hibernate through the convenient HibernateTemplate utility, which makes database access a piece of cake. Below is an example DAO.
Example DAO
public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {
public Product getProduct(Integer productId) {
return (Product)getHibernateTemplate().load(Product.class, productId);
}
public Integer saveProduct(Product product) {
return (Integer) getHibernateTemplate().save(product);
}
public void updateProduct(Product product) {
getHibernateTemplate().update(product);
}
}
Being Lazy in the Business Layer
Even outside the view, the Spring Framework makes it easy to use lazy load initialization, through the AOP interceptor HibernateInterceptor. The hibernate interceptor transparently intercepts calls to any business object configured in the Spring application context, opening a hibernate session before the call, and closing the session afterward. Let's run through a quick example. Suppose we have an interface BusinessObject:
public interface BusinessObject {
public void doSomethingThatInvolvesDaos();
}
The class BusinessObjectImpl implements BusinessObject:
public class BusinessObjectImpl implements BusinessObject {
public void doSomethingThatInvolvesDaos() {
// lots of logic that calls
// DAO classes Which access
// data objects lazily
}
}
Through some configurations in the Spring application context, we can instruct the HibernateInterceptor to intercept calls to the BusinessObjectImpl allowing it's methods to lazily access data objects. Take a look at the fragment below:
<beans>
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl">
<property name="someDAO"><ref bean="someDAO"/></property>
</bean>
<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="businessObjectTarget"/></property>
<property name="proxyInterfaces">
<value>com.acompany.BusinessObject</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
</list>
</property>
</bean>
</beans>
When the businessObject bean is referenced, the HibernateInterceptor opens a hibernate session and passes the call onto the BusinessObjectImpl. When the BusinessObjectImpl has finished executing, the HibernateInterceptor transparently closes the session. The application code has no knowledge of any persistence logic, yet it is still able to lazily access data objects.
Being Lazy in your Unit Tests
Last but not least, we'll need the ability to test our lazy application from J-Unit. This is easily done by overriding the setUp and tearDown methods of the TestCase class. I prefer to keep this code in a convenient abstract TestCase class for all of my tests to extend.
public abstract class MyLazyTestCase extends TestCase {
private SessionFactory sessionFactory;
private Session session;
public void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
session = SessionFactoryUtils.getSession(sessionFactory, true);
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
}
protected Object getBean(String beanName) {
//Code to get objects from Spring application context
}
public void tearDown() throws Exception {
super.tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
}
}
( Jul 08 2004, 09:39:55 AM EDT ) Permalink Comments [2]
Trackback URL: http://jroller.com/trackback/kbaum/Weblog/orm_lazy_initialization_with_dao
Comments:
A few things to keep in the back of your mind if you take this approach; 1. If any errors occur while attempting to lazy load relationships in the view (JSP) it would be hard to present a nice error to the user. 2. This would result in at least 2 hibernate sessions (db connections being open for any one request), so you might want to up the number of connections available. Cheers, Dan
Posted by Dan Washusen on July 08, 2004 at 09:02 PM EDT #
I am a little confused on why it would be difficult to show a nice error jsp. Couldn't we just use the provided servlet container error page mechanisms? In regards to the 2 hibernate sessions being opened. Are you saying that the OpenSessionInViewInterceptor would be run twice if an exception was thrown? Thanks for your feedback!
1、我認為最關鍵的,是要讓mm看到你的上進心。??
男人的最大魅力在于事業有成,年輕人工作時間不長談不上“有成”,這時候你就要讓mm覺得你是
????個有上進心的人。??
別的可以胡說八道,但這個問題不能含糊,你一定要告訴mm,你對未來充滿信心,你不滿足于現狀,并且你已經有了長遠的計劃,總之你的未來不是夢。??
??
2、要顯得有信心、有責任心??
不要像個小孩子,女孩子都很懶希望能找個依*,你要拿出自己的信心和責任心來。??
有一個錯的選擇總比沒有選擇要好的多。??
??
3、不要太正經,但也不要太隨?nbsp;?
該正經的地方就正經,該調侃的的時候就調侃。??
女孩子都喜歡有點玩世不恭的男人,所以別顯得對什么都特別在意,那樣太呆板。??
??
4、顯得成熟一點??
遇事鎮定、從容不迫的男人對mm有致命的吸引力。??
??
二、如何與mm展開進一步接觸(時間:開始追的階段)??
??
1、這個階段最關鍵的是不能著急,不要把事情弄的那么清楚,讓人家一眼就能看出你在追人家。??
想一想,一般人都不會一眼就看上你,但也不會看一眼就討厭你,都是老百姓家的孩子(除非你長得象周潤發劉德華或者凱文科斯特納),好感是需要隨著了解的不斷增加而實現的,所以問題的關鍵是你要得的進一步發展的機會。??
站在女孩子的角度替人家想一想:你這么直接了當的沖過來要搞對象,女孩子肯定有心理壓力。這要是接觸一陣后發現不喜歡你,那不就成了耍你了么?所以如果你開始就擺出志在必得的姿勢出來,基本上會被立刻悶回去。??
??
2、要低姿態起步??
首先要把關系定位成“朋友”,本來是“普通朋友”,你希望成為“好朋友”,有品位的還可以要求對方成為“紅顏知己”什么的,總之千萬不要說“追你”。??
你想想,你如果根本不提“追”,那么女孩子也就更沒機會“拒絕”你——你沒追她怎么拒絕你?!??
這樣可以減輕女孩子的心理壓力,使你們能順利的交往下去。不要幻想認識三天就答應嫁給你,要充分的交往、了解,感情不是憑空產生的。??
??
3、交往的過程中不要太急躁??
要有張有弛,不要整天纏著人家,誰這樣對你,你也會膩。我有個好朋友對我說,追女孩子的關鍵是八個字—— “忽冷忽熱、欲擒故縱”(這是我同學多少年心血的結晶)。??
??
你整天纏著人家自然不覺得你好,你適當的冷個一兩天,女孩子就會想起你在的好處了。??
??
還有就是不要拿出“非你不娶”的志氣來,太掉價了不好,有時候可以耍點花招。??
??
4、要適當的創造機會??
前面說了,不要使事情立刻變成“你在追別人”,而你又需要得到接近女孩子的機會,這時就要看你的創造力了。??
你可以搜集情報,想辦法把守株待兔變成一場邂逅;也可以裝做漫不經心的找出最最充足的理由邀請對方和你一起做什么事。??
總之這個是最有技術含量的地方,實在不行可以找前輩請教。??
5、切忌切忌:隨便送人家禮物是不禮貌的??
有些人追女孩子心切,喜歡經常買東西送人家,殊不知追女孩子最忌諱這個。??
俗話說“無功不受祿”,你這樣送人家東西就是在施加壓力,人家會覺得欠你的,所以會想辦法還給你,如果沒辦法還給你就會想辦法不和你交往,免得總是欠你人情。??
如果你想顯示自己的誠意,倒不妨請女孩子一起消費,比如說找好的餐廳吃飯,或者找貴的地方一起玩什么的,女孩子自然能看出你花了很多錢,但錢終究是兩個人一起花了而不是變成東西帶回家。??
??
三、“女朋友”到底是什么???
??
1、“女朋友”是一種事
實,而不是一份承諾??
你和女孩子開始交往,從“普通朋友”變成“好朋友”,再到“非常非常好、無話不談的朋友”,某一個陽光燦爛的午后,你“不小心”拉了她的手;“月上柳梢頭”,你突然襲擊吻了她。這時她就已經是你的女朋友了,無論她是否承認,她心理已經認為你是他男友了。??
我知道最高明的,直到上床了都沒問過“你是否愿意做我女朋友”,最后還是女孩子急了:“你怎么還不求我做你女朋友啊!”??
所以說,千萬不要急于把窗戶紙捅破,情況越朦朧對你越有利。??
??
2、“表白”是什么???
前面說了,表白實際上就是一個形式而已,正確的順序應該是:事實上已經成為你女朋友了,你才能向人家表白,水到渠成。 很多人弄不明白這個問題,總以為人家先答應做自己女朋友,然后再如何如何,我只能說他非常非常“單純”,也非常非常“愚蠢”。??
??
3、有沒有“迫不得已非表白不可”的時候???
??
有,比如說出現第三者,或者你和女孩子關系沒有成熟但兩個人可能分開一段時間。??
這時候的表白就是條件不成熟的表白,風險非常大,類似于下圍棋的時候形勢嚴峻,落後的一方迫于無奈放出“勝負手”,贏了就贏了,輸了也只能說“倒霉都是天生的”。??
??
4、“愛”字不要輕易出口??
經常看見論壇出現“大膽的表白”,說實話我真的認為這是非常不成熟的一種表現。“愛”是一個神圣的字,意味著追求,也意味著承諾,甚至體現出一種責任。??
隨便說“愛”的男人是不負責任的。??
??
四、文明戀愛,不可強求??
??
1、不是每個mm都能追到手的??
好女孩總會有很多人追,不可能遂了每個人的心愿,總會有失敗者。舉個例子,就算你刻苦鉆研掌握了最搞超的追mm原理,你一樣追不上twins里的任何一個。??
換個角度考慮問題,一個小學沒畢業的農村小保姆,即使對你再好,每個月賺600給你買700的禮物(透支),愿意為你“當牛做馬”,你也不會愛上她。如果她每天哭哭啼啼的纏著,你肯定覺得煩。??
所以說愛情是需要物質基礎的,至少需要平衡。??
??
2、追mm做是一種嚴肅的社會活動??
千萬不要把人家搞煩了,要給自己留后路。大丈夫何患無妻?有些mm確實勢利眼(少數),如果不服氣,你可以發憤圖強,用事實證明“她當時瞎了眼”,絕對不要誤人誤己。 ??
??
最后補充一點千萬不要在mm面前顯得憤世嫉俗,憤世嫉俗有時候意味著“你很失敗”