Spring框架知識點

Spring簡介

使用Spring可使用簡單的JavaBean實現之前EJB實現的功能, Spring是一個IOC和AOP容器框架java

  • Spring是非侵入式, 開發應用過程當中能夠不依賴Spring的API
  • 依賴注入
  • 面向切面變成
  • 容器
  • 框架
  • 一站式: IOC和AOP的基礎上能夠整合企業開源框架和第三類庫

public class HelloWorld {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void hello() {
        System.out.println("hello: " + name);
    }
}

public class Main {

    public static void main(String[] args) {

        // 建立HelloWorld 的一個對象
        HelloWorld helloWorld = new HelloWorld();
        // 爲 name 屬性賦值
        helloWorld.setName("kong");
        // 調用hello 方法
        helloWorld.hello();

    }
}
複製代碼

一個簡單的helloWorld程序,其中第一步建立對象 和 第二步爲屬性賦值能夠交給Spring框架來完成spring

// 1. 建立Spring IOC 容器對象,容器對象會調用構造器並調用HelloWorld類中的setName方法
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 從IOC容器中獲取Bean實例
        HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
// 3. 調用 hello 方法
        helloWorld.hello();
複製代碼
<bean id="helloWorld" class="com.atguigu.spring.beans.HelloWorld">
        <property name="name" value="Spring"></property>
    </bean>

複製代碼

Spring中的IOC & DI概述

IOC是翻轉資源獲取的方向, 傳統資源查找方式是組件向容器發起請求查找資源, 容器適時的返回資源, 應用了IOC以後,是容器主動將資源推送給它所管理的組件,組件要作的是選擇合適的方式來接收資源編程

DI: 組件以一些預先定義好的方式接受來自容器的資源注入設計模式

// 傳統方式
A a = getA();
B b = getB();
b.setA(a)
複製代碼
// 使用IOC實現
B b = getB();
複製代碼

IOC前生

  • 分離接口與實現
    • 報表生成器: 生成PDF 或 HTML不一樣類型的報表

  • 採用工廠設計模式
  • 使用反轉控制 Service

##Spring配置Bean Spring屬性配置細節 如何配置Beanbash

  • 配置方式: 基於XML文件的格式app

    <bean id="helloWorld" class="com.atguigu.spring.beans.HelloWorld">
        <property name="name" value="Spring"></property>
    </bean>
    class: 用於建立 bean的全類名,經過反射方式在IOC中建立bean, 要求bean中必需要有無參數的構造器
    id: 用於獲取容器中的bean,id值惟一
     
    複製代碼
  • Bean的配置方式: 經過全類名(反射)/經過工廠方法(靜態工廠方法 & 實例工廠方法)、FactoryBean框架

  • IOC容器BeanFactory & ApplicationContext概述ide

    • ApplicationContext 表明IOC容器 兩種類型的IOC容器實現
      • BeanFactory: IOC容器的基本實現
      • ApplicationContext: 提供了更多的高級特性,是BeanFactory的子接口
      • BeanFactory是Spring框架的基礎設施,面向Spring自己, ApplicationContext面向框架的使用者, 應用場合多直接使用ApplicationContext而非底層的BeanFactory
  • 依賴注入的方式:ui

    • 屬性注入(實際中最經常使用):
      • 經過setter方法注入Bean的屬性值或依賴的對象
      • 屬性注入使用元素,使用name屬性制定Bean的屬性名稱,value屬性(或子節點指定屬性值)
    • 構造器注入:
      • 經過構造方法注入Bean的屬性值或依賴的對象,保證了Bean實例在實例化後就可使用
      • 構造器注入在<constructor-arg>元素裏聲明屬性,沒有name屬性
      • 混合使用index type 來指定參數的位置和參數的類型以區分重載的構造器
      // 使用value屬性值類配置
      <constructor-arg value="Audi" index="2"></constructor-arg>
      // 使用value子節點來配置
      <constructor-arg type="int">
          <value>250</value>
      </constructor-arg>
      複製代碼
      • 參數列表 參數類型
  • 字面值: 能夠用字符串表示的值,能夠經過元素標籤或value屬性進行注入,基本數據類型及其封裝類、String等類型均可以採用字面值注入的方式this

  • 使用property的ref屬性創建bean之間的引用關係

    • 使用元素創建引用
    • 使用內部Bean(不能被外部Bean引用,只能在內部使用): 在屬性或構造器中包含Bean的聲明,這樣的Bean被稱爲內部Bean
  • 使用集合的基本標籤進行集合的配置,例如list,array,``

  • 配置Properties屬性值

  • 配置獨立的集合bean,以供多個bean進行引用,使用util命名空間

<util:list id="cars">
    <ref bean="car"/>
    <ref bean="car2"/>
</util:list>


複製代碼

使用p命名空間來爲bean的屬性賦值 <bean id="person" class="com.atguigu.spring.beans.Person" p:age="30" p:name="Queen" p:cars-ref='cars'></bean>

5.Srping 自動裝配

什麼是自動裝配: 在<bean>的autowire屬性裏制定自動裝配的模式

  • byType(根據類型自動裝配): 若出現多個類型相同的Bean,Spring沒法斷定,因此沒法進行自動裝配
  • byName(根據名稱自動裝配): 必須將目標Bean的名稱和屬性名設置的徹底相同

在Person類當中定義了setter setter裏面有名字的信息,

自動裝配的缺點:

  • 必須全部的屬性都使用自動裝撇
  • 使用了裝配方式只能是byName 或 byType,不夠靈活
  • 通常狀況下不多使用自動裝配功能,明確清晰的配置文檔更好

6.Spring Bean之間的關係

繼承關係: 配置上的繼承關係 bean配置的重用 使用<parent>關鍵字

依賴關係: 某些bean要在前面建立 depends-on關鍵字 好比要求在配置Person時,必需要有一個關聯的car! 換句話說person這個bean依賴於Car這個bean

7.Spring Bean的做用域

使用scope來設定做用域 默認狀況下是單例模式,相同類型的bean都是一樣的 prototype: 原型 容器初始化時不建立bean實例,而在每次請求時都建立一個新的Bean實例,並返回

8.Spring使用外部屬性文件

好比須要用到系統部署的細節信息(好比文件路徑),這些信息須要和Spring文件分離

使用PropertyPlaceholderConfigurer的BeanFactory 後置處理器,該處理器容許用戶將Bean配置的部份內容外移動到屬性文件中,能夠在Bean配置文件中使用 ${var}變量來從外部屬性文件中加載屬性,並使用這些屬性來替換變量

9. Spring SpEL語句

可使用SpEL語句進行擴展性的操做:

  • 引用類的靜態屬性
  • 使用SpEL 語句來應用其餘的Bean、其餘Bean的屬性、
  • 使用運算符

10.Spring 管理Bean的聲明週期

Spring容許在Bean聲明週期的特定點執行定製的任務 SpringIOC 容器對Bean的聲明週期進行管理的過程:

  • 經過構造器或工廠方法來建立Bean實例
  • 爲Bean的屬性設置值和對其它Bean的引用
  • 調用Bean的初始化方法
  • 使用Bean
  • 當容器關閉時,調用Bean的銷燬方法

在Bean的聲明中設置init-methoddestroy-method屬性,爲Bean指定 初始化和銷燬方法

在類裏面先將init方法(名字能夠自定義,保證對應就行)定義好,
<bean id="car" class="..." init-method="init" destroy-method="destroy">

複製代碼

ctx.close(): 關閉IOC容器

建立Bean後置處理器 Bean後置處理器容許在調用初始化方法先後對Bean進行額外的處理

經過工廠方法配置Bean的

靜態工廠方法: 直接調用某一個類的靜態方法就能夠返回Bean的實例

  • class: 指向靜態工廠方法的全類名
  • factory-method關鍵字: 指向靜態工廠方法的名字
  • constructor-arg: 若是工廠方法須要傳入參數,則使用constructor-arg來配置參數
<bean id="car1" class="..." factory-method="getCar">
    <constructor-arg value="audi"></constructor-arg>
</bean>
複製代碼

實例工廠方法:: 先要建立工廠自己,再經過調用工廠

  • factory-bean: 指向實例工廠方法的bean
  • factory-method關鍵字定義工廠bean的方法
<bean id="carFactory" class="..."></bean>
<bean id="car2" factory-bean="" factory-method="..">
複製代碼

11. 使用Spring的FactoryBean配置Bean

FactoryBean 是Spring提供的一個接口

  • 自定義的FactoryBean須要實現FactoryBean
  • class: 指向FactoryBean的全雷鳴
  • property: 配置FactoryBean的屬性 實際返回的實例是FactoryBean的getObject() 返回的實例 便於有時候配置Bean的時候用到Spring當中的其它Bean
  • getObject()
  • getObjectType()
  • isSingleton()

13. 基於註解配置Bean

在classpath中掃描組件

  • @Component: 基本註解,標識一個Spring管理的組件
  • @Respository: 標識持久層組件
  • @Service: 標識服務層(業務層)
  • @Controller: 表現層組件 Spring默認命名策略: 使用非限定類名時,第一個字母小寫, 也能夠在註解中經過value屬性值標識組件的名稱

須要在Spring配置文件中聲明<context:component-scan> 來限定掃描哪些包

指定一個須要掃描的基類包,Spring容器會掃描基類包以及其子包中的全部類,多個包能夠經過逗號分隔 context:exclude-filter: 排除指定組件 context:include-filter: 包含表達式組件

14. 基於註解配置Bean2

16. Spring AOP基礎

一個計算器接口,

須要完成兩個額外的需求, 生成日誌 + 進行驗證

日誌代碼差很少 核心代碼混亂,愈來愈多非業務需求,每一個方法在處理 還要兼顧其餘多個關注點

代碼分散: 只是爲了知足一個單一需求,不得不在多個模塊(方法)裏屢次重複相同的日誌代碼,若是日誌需求發生變化,必須修改全部模塊.

AOP方式解決

動態代理解決 代理設計模式: 使用一個代理將對象包裝起來,而後用該代理對象取代原始對象,任何對原始對象的調用都要經過代理

public class ArithmeticCalculatorLoggingProxy {
    
    //要代理的對象
    private ArithmeticCalculator target;
    
    public ArithmeticCalculator getLoggingProxy() {
        ArithmeticCalculator proxy = null;
        
        // 代理對象由哪個類加載器負責加載
        ClassLoader loader = target.getClass().getClassLoader();
        // 代理對象的類型,即其中有哪些方法
        Class[] interfaces = new Class[]{ArithmeticCalculator.class};
        // 當調用代理對象其中的方法時,須要執行的代碼
        InvocationHandler h = new InvocationHandler() {
            /** * @param: proxy: 正在返回的代理對象,通常狀況下,invoke方法中不使用 * @param: method: 正在被調用的方法 * @args: 調用方法時,傳入的參數 */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("invoke...");
                return 0;
            }
        };
        proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
        return proxy;
    }
}
複製代碼

動態是什麼意思?體如今哪裏?

橫切關注點方法 在應用AOP時,須要定義公共功能,但能夠明肯定義功能在哪裏,以何種方式應用,而且沒必要修改受影響的類.

AOP的好處:

  • 每一個事務邏輯位於一個位置,代碼不分散,便於維護和升級
  • 業務模塊更簡潔,只包含核心業務代碼

計算器加減乘除的例子:

切面: 通知: 切面中的每個方法就是通知 鏈接點: 程序執行的某個特定位置 一個具體的存在 切點: 看不見 經過切點定位到特定鏈接點

Spring 前置通知

在配置文件中加入AOP的命名空間 xmlns:aop="..."

基於註解的方式: 在配置文件中加入以下配置: 把橫切關注點的代碼抽象到切面的類中 切面首先是一個Java bean,須要加入@Component註解 使用@Aspect註解標註出切面,

  • 提供5個註解來定義通知
    • @Before: 方法執行前
    • @After: 方法執行後
    • @AfterReturning: 通知方法在目標方法返回後調用
    • @AfterThrowing: 通知方法在目標方法拋出異常後調用
    • @Around: 環繞

execution() * 能夠表示任意修飾符及任意返回值

20. Spring切面的優先級

使用@Order 指定切面的優先級,值越小,優先級越高

21. 重用切點表達式

從新用execution 那一坨東西 定義一個方法,用於聲明切入點表達式, 以後再用到該切點的地方就直接調用該方法便可聲明對應切點

@Pointcut("...")
public void declareJointPointExpression(){}
複製代碼

22. 基於配置文件聲明切面

<aop:config>
    <aop:aspect ref="audience">
        <aop:before
            pointcut="..." method="方法名"/>
        <aop: after-returnning
            pointcut="execution(...)"/>
    </aop:aspect>
</aop:config>

複製代碼

25. Spring事務準備

必須爲不一樣的方法重寫相似的樣板代碼,存在大量的重複部分

public void purchase(String isbn, String username) {
    Connection conn = null;
    try {
        conn = dataSource.getConnection();
        conn.setAutoCommit(false);
        ...
        conn.commit();
    } catch (SQLException e) {
        e.printStackTrace();
        if (conn != null) {
            try {
                conn.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        throw new RuntimeException(e);
    } finally {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}


複製代碼

編程式 聲明式

Spring

配置事務管理器 啓用事務註解 @Transactional

相關文章
相關標籤/搜索