Spring入門(一)— IOC、DI

来源:https://www.cnblogs.com/gdwkong/archive/2018/02/18/8453053.html
-Advertisement-
Play Games

本文簡要介紹了Spring,及Spring中IOC及DI的基本使用。 ...


一、Spring介紹

  Spring 是一個開源框架,是為瞭解決企業應用程式開發複雜性而創建的。框架的主要優勢之一就是其分層架構,分層架構允許您選擇使用哪一個組件,同時為 J2EE 應用程式開發提供集成的框架。簡單來說,Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源框架。

  Spring是2003年興起的一個輕量級的java框架, 由 Rod Johnson 在其編著的《Expert one on one J2EE design and development》一書中闡述的思想和理念衍生而來。

  Spring 有兩個核心 IOC & aop

  • IOC

IOC 的全稱是 Inversion Of Control 翻譯過來是控制反轉的意思。 把對象的創建工作交給框架來完成

UserService userService = new UserServiceImpl(); ---> 問框架要對象

  • AOP

AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程

1. IOC的演變

  • 從早期的直接new具體類 ---> 面向介面編程

  • 面向介面編程 --使用工廠

  • 使用Spring來替代

 

 

2. Spring入門

  1. 導入jar包

    beans | code | context | expression 4個日誌jar包 , log4j.properties

  2. 編寫業務邏輯類

public interface UserService {
​
    void save();
}
​

public class UserServiceImpl implements UserService {
​
    @Override
    public void save(){
        System.out.println("調用了UserServiceImpl的save方法~!~!");
    }
​
}
  1. ml托管業務邏輯類

  在src下,創建一個xml, 名字隨意。 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="us" class="com.pri.service.impl.UserServiceImpl"></bean>
    
</beans>
  1. 創建工廠,問工廠要對象

public class MainTest {
​
    @Test
    public void testSave(){
        /*
        UserService userService = new UserServiceImpl();
        userService.save();*/
        
        //1. 創建工廠
     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        //2. 問工廠要實例對象
        UserService userService =(UserService) context.getBean("us");
        
        //3. 調用方法
        userService.save();
    }
}

3. 配置詳解

  • xml解釋

   <!--  bean 標簽是用來告訴spring,需要幫忙創建什麼類的實例 
   
        id | name : 標識符  , 以後拿著id的值就能問spring要對應類的實例。
        class : 托管類的全路徑
        scope: 用於表示生成的實例模式
            spring預設生成的實例是單例。  scope="prototype" 表示生成多例
        
        init-method: 生成實例之後,調用的方法
        destroy-method: 銷毀實例的時候調用的方法
   -->
    <bean id="us" class="com.pri.service.impl.UserServiceImpl" scope="prototype"
        init-method="init" destroy-method="destroy">
    </bean>
  • 代碼解釋

public class MainTest {
​
    @Test
    public void testSave(){
        /*
        UserService userService = new UserServiceImpl();
        userService.save();*/
        
        //1. 創建工廠 , 需要告訴工廠,xml文件在哪裡。  不會這麼寫
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        //2. 問工廠要實例對象  , 可以讓工廠送過來
        UserService userService =(UserService) context.getBean("us");
        
        //3. 調用方法
        userService.save();
        
        //關閉工廠  以後一般不關閉工廠
        ((AbstractApplicationContext) context).close();
    }
}

二、IOC實例化方式

  把對象交給spring創建的方式

1. 無參構造方法【重點】

  要求托管類的務必提供無參構造方法,當然以後可以配置讓spring走有參構造

  • 代碼

public class UserServiceImpl implements UserService {
    
    //spring創建實例, 要求托管類預設提供無參構造方法。
    @Override
    public void save(){
        System.out.println("調用了UserServiceImpl的save方法~!~!");
    }
}
  • 配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="us" class="com.pri.service.impl.UserServiceImpl"></bean>
</beans>

2. 靜態工廠方法【瞭解】

要求提供工廠類,並且工廠的方法是靜態方法, 在方法裡面生成業務邏輯類的實例

  • 代碼

public class StaticFactory {
​
    public static UserService getBean(){
        System.out.println("要創建UserServiceImpl的實例了~~");
        return new UserServiceImpl();
    }
}
  • xml

<!-- 我們也是拿著us去問spring工廠要實例,  它直接就調用了StaticFactory的getBean方法拿到實例,然後返回 -->
<!-- 靜態工廠配置 -->
<bean id="us" class="com.pri.factory.StaticFactory" factory-method="getBean"></bean>

3. 實例工廠方法【瞭解】

  • 代碼

public class InstanceFactory {
​
    public UserService getBean(){
        System.out.println("要創建UserServiceImpl的實例了~~");
        return new UserServiceImpl();
    }
}
  • xml

<bean id="factory" class="com.pri.factory.InstanceFactory"/>
<bean id="us" factory-bean="factory" factory-method="getBean"></bean>

  後面的兩種工廠的配置,開發當中幾乎不會用。

三、依賴註入

  • 什麼是依賴註入?

  DI : 全稱是 dependency Injection 翻譯過來是依賴註入 本意是在實例化對象的時候,對它裡面的成員屬性進行值的註入。

public class UserServiceImpl{
  
  private String name;
  
  
  //1. set方法
  public void setName(String name){
    this.name=name;
  }
}
​
​
UserServiceImpl us = new UserServiceImpl();
us.setName("zhangsan");
​
//現在實例的創建是工廠來完成,我們想讓工廠創建實例的時候,順便把成員變數給賦值了。
  • 給成員變數賦值的方式【DI的方式】

  ①set方法

  ②有參構造

1. 依賴註入的方式【重點】

註入的方式有兩種: 有參構造 | set方法

  1. 採用有參構造完成依賴註入

  提供有參構造方法

  • 代碼

public class UserServiceImpl implements UserService {
    
    private String address;
​
    public UserServiceImpl(String address) {
        super();
        this.address = address;
    }
​
    @Override
    public void save(){
        System.out.println("調用了UserServiceImpl的save方法~!~!=="+address);
    }
​
}
  • xml

<bean id="us" class="com.pri.service.impl.UserServiceImpl" >
    <!-- 指定構造的參數, name: 參數的名稱, values: 參數的值 -->
    <constructor-arg name="address" value="深圳"/>
</bean>

2. 採用set方法完成依賴註入

  • 代碼

public class UserServiceImpl implements UserService {
    
    private String address;
​
    public void setAddress(String address) {
        this.address = address;
    }
​
    @Override
    public void save(){
        System.out.println("調用了UserServiceImpl的save方法~!~!=="+address);
    }
}
  • xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="us" class="com.pri.service.impl.UserServiceImpl" >
        <property name="address" value="寶安"/>
    </bean>
</beans>

2. 註入數據類型的演練

1. 集合類型

a. 數組類型
  • 代碼

public class UserServiceImpl implements UserService{
    
    private String []  address;
    
    public void setAddress(String [] address) {
        this.address = address;
    }
  ...
}
  • xml

<property name="address" >
    <array>
        <value>北京1</value>
        <value>北京2</value>
        <value>我愛北京天安門,天安門很大</value>
    </array>
</property> 
b. list集合
  • 代碼

public class UserServiceImpl implements UserService{
    private List<String>  address;
    
    public void setAddress(List<String> address) {
        this.address = address;
    }
  ...
} 
  • xml

<property name="address">
    <list>
        <value>北京1</value>
        <value>北京2</value>
        <value>我愛北京天安門,天安門很大</value>
    </list>
</property>
c. map集合
  • 代碼

public class UserServiceImpl implements UserService{
​
    private Map<String ,Object> address;
    
    public void setAddress( Map<String ,Object> address) {
        this.address = address;
    }
    ...
}
  • xml

<property name="address">
    <map>
        <entry key="地址1" value="北京1"/>
        <entry key="地址2" value="北京2"/>
        <entry key="地址3" value="北京3"/>
    </map>
</property>

2. 對象類型

  • 代碼

public class UserServiceImpl implements UserService {
    
    private UserDao userDao;
    
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
​
    @Override
    public void save(){
        System.out.println(" ==調用了UserServiceImpl的save方法~!~!==");
        
        /*UserDao userDao =new UserDaoImpl();  //創建對象  ---》 IOC  ----> bean標簽
        userDao.save();*/
        
        //1. 我們自己創建對象,然後自己用。
        
        //2. 工廠創建對象,我們去問它要對象
        
        //3. 工廠創建對象,讓工廠自己送過來對象。 --- 》 註入對象
        
        userDao.save();
    }
}
  • xml

<!-- 讓spring創建UserServiceImpl的實例 -->
    <bean id="us" class="com.pri.service.impl.UserServiceImpl" >
    
<!-- 讓spring調用UserServiceImpl的setUserDao的方法,並且把剛纔創建好的ud的那個實例當成參數,傳遞進去。
        這就完成了對象的註入 -->
        <property name="userDao" ref="ud"></property> 
    </bean>
    
    <!-- 讓spring創建UserDaoImpl的實例 -->
    <bean id="ud" class="com.pri.dao.impl.UserDaoImpl"></bean>

3.註入的xml寫法細節【瞭解】

依賴註入的方式已經固定化了,就是 有參構造 | set方法。 但是spring擔心程式員在xml的配置要寫的代碼很多,然後程式員就不喜歡用了。所以spring針對xml的註入,提出了兩種簡化寫法 : p 名稱空間 | c名稱空間

  • p 名稱空間

針對的是這個<property name="" /> , 也就表明瞭代碼裡面聲明註入的方式是 set方式

<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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="us" class="com.pri.service.impl.UserServiceImpl" p:address="北京">    
</bean>
  • c 名稱空間

針對的是這個<constructor-arg/>, 也就要求我們的代碼聲明註入的方式必須是有參構造

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="us" class="com.pri.service.impl.UserServiceImpl" c:address="北京">
</bean> 
  • SPEL 屬性註入

可以完成邏輯運算

<bean id="us" class="com.pri.service.impl.UserServiceImpl" >
        <property name="address"  value="#{1>2}"/>
</bean> 

四、整合Servlet

1. 初步整合

在servlet裡面創建工廠、然後獲取實例對象

public class ServletDemo extends HttpServlet {
​
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("調用了get方法~~~");
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService us = (UserService)context.getBean("us");
        us.save();
        ((AbstractApplicationContext) context).close(); 
    }
} 

2. 初步整合的問題

2個問題

1. 每次請求過來都會解析xml, 創建工廠。如果xml內容很多,就比較的耗時。
解決方法:
工具類 | 靜態代碼塊

2. 工廠創建的時機有點晚。 第一次使用的時候才會創建。

解決方法:
提前創建  --- 提前到項目發佈 --- 項目發佈之後,就會創建一個類的實例(ServletContext)-----ServletContextListner  
a. 如果是我們自己處理的,  定義監聽器, 然後在監聽器裡面創建工廠 存儲工廠到一個地方去,以便所有的servlet都能使用到工廠。 servletContext.
b. 監聽器不用你們寫了,工廠創建的代碼不用你們寫了。放到servletcontext也不用寫了。 配置監聽器。

3. 進階整合

把上面出現的問題給解決掉 ,必須要導入額外的jar包 spring-web-xxx.jar

只要項目一發佈,就立即創建工廠,那麼我們必須的抓住項目發佈的這個契機。 以前在servlet階段,學過一種東西監聽器 ,可以監聽作用域對象的創建與銷毀 , SerlvetContext, 這是最大的作用域,全局只有一個對象。 

  1. 在web.xml 中配置 監聽器 並且配置param 指定spring配置文件所在

 <!--  配置listener,目的就是讓項目發佈的回收,能夠創建工廠。但是創建工廠
  需要解析xml文件,它預設回到/WEB-INF/applicationContext.xml 
  要是找不到就報錯,除非我們告訴它,xml文件在哪裡 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <!-- 告訴listener, 配置文件在哪裡 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  1. 通過工具類獲取之前創建好的工廠

public class ServletDemo extends HttpServlet {
​
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        System.out.println("調用了get方法~~~");
        
        //ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        UserService us = (UserService)context.getBean("us");
        us.save();
        //((AbstractApplicationContext) context).close();
        
    }
    ...
}

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

-Advertisement-
Play Games
更多相關文章
  • 問題: 有一個國家發現了5座金礦,每座金礦的黃金儲量不同,需要參與挖掘的工人數也不同。參與挖礦工人的總數是10人。 每座金礦要麼全挖,要麼不挖,不能派出一半人挖取一半金礦。要求用程式求解出,要想得到儘可能多的黃金,應該選擇挖取哪幾座金礦? 動態規劃有三個核心元素:最優子結構、邊界、狀態轉移 方程式。 ...
  • 在ASP.NET Web API里使用Autofac 通過NuGet安裝Autofac.WebApi。(Nuget會安裝依賴的Autofac.dll)。 PM > Install-Package Autofac.WebApi 引用如下命名空間: using Autofac; using Autofa ...
  • 參考文獻:《大話設計模式》 一、單一職責原則(SRP) 定義:就一個類而言,應該僅有一個引起它變化的原因。 解釋:如果一個類承擔的職責過多,就等於是把這些職責耦合在一起,一個職責的變化可能會削弱或者抑制這個類完成其他職責的能力。 這種耦合會導致脆弱的設計,當變化發生時,設計會遭受到意想不到的破壞。 ...
  • SQL Server 2008基於策略的管理,基於策略的管理(Policy Based Management),使DBA們可以制定管理策略,並將這些策略應用到伺服器、資料庫以及數據環境中的其他對象上去。基於動作策略(Action Policy)的異常處理使開發人員可以為異常處理制定策略,簡單的說,動 ...
  • 較複雜的應用程式都是由多個項目組織成的,項目可以劃分成程式集(Assemblies)和宿主(Hosts),也就是應用程式的入口。 Assemblies 通常是常見的類庫項目,包括可以重用的功能以方便測試,通常包括下麵的組件: Views, Controllers 和 Models; 服務; 持久類 ...
  • 在.NET上現在存在許多的依賴註入容器, 如:Castle Windsor、StructureMap、Autofac 、Unity。 這裡主要介紹一下Autofac,Autofac和其他容器的不同之處是它和C#語言的結合非常緊密,在使用過程中對你的應用的侵入性幾乎為零,更容易與第三方的組件集成。Au ...
  • 1 學習計劃 1、datagrid使用方法(重要) n 將靜態HTML渲染為datagrid樣式 n 發送ajax請求獲取json數據創建datagrid n 使用easyUI提供的API創建datagrid(掌握) 2、實現取派員分頁查詢 n 調整頁面基於datagrid發送ajax請求 n 創建 ...
  • 員工與角色案例: 一個員工可以是多種角色(總監,經理),一種角色可以是多個員工(保潔) 這裡發現無法使用外鍵表達關係,多對多總是創建第三張表來維護關係 這張表至少兩列,都是外鍵,分別引用兩張表的主鍵 員工(用戶)實體類: package domain; //用戶實體 import java.util ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...