Java框架之Spring(三)

来源:https://www.cnblogs.com/1693977889zz/archive/2017/12/30/8151371.html
-Advertisement-
Play Games

本文主要介紹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)如果介面增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法。增加了代碼維護的複雜度。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 先把一個div設置成A4紙的大小,寬21cm,高29.7cm ```html ``` , ``` #abody { width: 21cm; height: 29.7cm; margin: 0 auto; overf... ...
  • 1.Properties類簡介 Properties類(Java.util.Properties),主要用於讀取Java的配置文件,各種語言都有自己所支持的配置文件,配置文件中很多變數是經常改變的,這樣做也是為了方便用戶,讓用戶能夠脫離程式本身去修改相關的變數設置。像Python支持的配置文件是.i ...
  • 簡單工廠又稱為靜態工廠方法(static factory method)模式,簡單工廠是由一個工廠來決定創建出哪一種個體的實現,在很多的討論中,簡單工廠做為工廠方法模式(Factory Method)的一個特殊案例出現. 這個模式封裝的變化點是什麼? 這是每一個模式都應該考慮的核心問題,一定要記得, ...
  • 偶然看見這樣一個案例,先上代碼: public class GenericAdd{ //泛型方法實現兩個數相加 public <T extends Number> double add(T t1, T t2){ double sum = 0.0; sum = t1.doubleValue() + t ...
  • MarkDown筆記 目的 寫這篇文章,一來是記錄一下,以備日後使用;二來是我看到網上很多關於MarkDown的語法總結得不是很全面。 語法 1.標題 標題有兩種表示方式,第一種是Atx,這是我見的最多的;第二種是Setext。下麵分別來介紹一下。 (1)Atx 使用 表示,和HTML的h1~h6標 ...
  • 讓我們先來預覽一下代碼運行效果吧: 首先分析163郵箱登陸頁面的網頁結構(按F12或單擊滑鼠右鍵選擇審查元素) 1、定位到登陸框(註意登錄框是一個iframe,如果不定位到iframe的話是無法找到之後的郵箱地址框和密碼輸入框的) 2、定位到郵箱地址框(name='email') 3、定位到密碼輸入 ...
  • C 語言的 static 關鍵字有三種(具體來說是兩種)用途: 1. 靜態局部變數:用於函數體內部修飾變數,這種變數的生存期長於該函數。 要明白這個用法,我們首先要瞭解c/c++的記憶體分佈,以及static所在的區間。 對於一個完整的程式,在記憶體中的分佈情況如下圖: 1.棧區: 由編譯器自動分配釋放 ...
  • 1排版 1 1相對獨立的程式塊之間、變數說明之後必須加空行。 示例:如下例子不符合規範。 if (!valid_ni(ni)) { ... // program code } repssn_ind = ssn_data[index].repssn_index; repssn_ni = ssn_dat ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...