spring入門筆記

這是我本身學習韓順平老師spring視頻的筆記,我的認爲初學spring的韓順平老師的講的很好,比較通俗易懂,資源地址我已經給了,能夠本身配合視頻看。主要介紹了ioc和aop,這也是spring框架最核心的部分。

相關代碼地址:https://github.com/weiliangchun/JavaEE/tree/master/SpringHSP
java

1、spring的快速入門案例

  1. spring是什麼
    struts 是 web 框架(jsp/action/actionform)
    hibernate 是 orm 框架,處於持久層
    spring 是容器框架,用於配置bean,並維護bean之間關係的框架

spring 中有一個很是重要的概念:bean(是java中的任何一種對象 javabean/service/action/數據源/dao),IOC(控制反轉),DI(依賴注入)git

spring的層次圖

快速開發

開發一個spring項目github

  1. 引入spring的開發包(最小配置spring.jar 該包把經常使用的jar都包括, 還要 寫日誌包 common-logging.jar
  2. 建立spring的一個核心文件 applicationContext.xml, [hibernate有核心 hibernate.cfg.xml struts核心文件 struts-config.xml], 該文件通常放在src目錄下,該文件中引入 xsd文件 :
    能夠從給出的案例中拷貝一份.
  3. 配置bean
<!-- 在容器文件中配置bean(service/dao/domai/action/數據源) -->
<!-- bean元素的做用是,當咱們的spring框架加載時候,spring就會自動建立一個bean對象,並放入內存
    UserService userService = new UserService();
    userService.setName("春春");
 -->
<bean id="userService" class="com.service.UserService">
    <!-- 這裏就體現出注入的概念 -->
    <property name="name">
        <value>春春</value>
    </property>
</bean>
  1. 在Test.java中。怎麼使用
//咱們如今用使用spring來完成上面的任務
//1.獲得spring的applicationContext對象(容器對象)
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService us = (UserService) ac.getBean("userService");
us.sayHello();
  1. 細節討論
    傳統的方法和使用spring的方法區別
  • 使用spring ,沒有new 對象,咱們把建立對象的任務交給spring框架
  • spring的運行原理圖
    spring的運行原理圖web

  • 咱們再看spring
    對上面案例總結:
    spring其實是一個容器框架,能夠配置各類bean,而且能夠維護bean與bean的關係,當咱們須要使用某個bean的時候,咱們能夠getBean(id),使用便可.
    IOC是什麼?
    ioc(inverse of controll ) 控制反轉: 所謂控制反轉就是把建立對象(bean),和維護對象(bean)的關係的權利從程序中轉移到spring的容器(applicationContext.xml),而程序自己再也不維護.
    DI是什麼
    di(dependency injection) 依賴注入: 實際上di和ioc是同一個概念,spring設計者認爲di更準確表示spring核心技術spring

學框架,最重要的就是學習各個配置數據庫

2、開始spring

點我查看參考代碼文件夾編程

spring提倡接口編程,配合DI技術能夠達到層與層的解耦數組

舉例說明

如今咱們體驗一下spring的DI配合接口編程,完成一個字母大小寫轉換的案例
思路:緩存

  1. 建立一個接口 ChangLetter
  2. 兩個類實現這個接口
  3. 把對象配置到spring容器中
  4. 使用

經過上面的案例,咱們能夠初步體會到DI配合接口編程,的確能夠減小層(web層)和業務層的耦合度session

裝配bean

從ApplicationContex 應用上下文容器中獲取bean和從bean工廠容器中獲取bean
結論:

  1. 若是使用ApplicationContext ,則配置的bean若是是 singlton無論你用不用,都被實例化.(好處就是能夠預先加載,缺點就是耗內存)
  2. 若是是 BeanFactory ,則當你獲取beanfacotry時候,配置的bean不會被立刻實例化,當你使用的時候,才被實例(好處節約內存,缺點就是速度)
  3. 規定: 通常沒有特殊要求,應當使用ApplicatioContext完成(90%)
bean的scope細節
做用域 描述
sigleton 在每一個Spring IoC容器中一個bean定義對應一個對象實例。
prototype 一個bean定義對應多個對象實例。
request 在一次HTTP請求中,一個bean定義對應一個實例;即每次HTTP請求將會有各自的bean實例,它們依據某個bean定義建立而成。該做用域僅在基於web的Spring ApplicationContext情形下有效。
session 在一個HTTP Session中,一個bean定義對應一個實例。該做用域僅在基於web的Spring ApplicationContext情形下有效。
global session 在一個全局的HTTP Session中,一個bean定義對應一個實例。典型狀況下,僅在使用portlet context的時候有效。該做用域僅在基於web的Spring ApplicationContext情形下有效。

入門案例:

//獲取兩個student  
Student s1=(Student) ac.getBean("student");  
Student s2=(Student) ac.getBean("student");  
System.out.println(s1+" "+s2);
  • request
  • session
  • global-session
    是在web開發中纔有意義

三種獲取ApplicationContext對象引用的方法

  1. ClassPathXmlApplicationContext -> 經過類路徑
  2. FileSystemXmlApplicationContext -> 經過文件路徑
  3. XmlWebApplicationContext

3、bean的生命週期 ==(重要)==

點我查看參考代碼文件夾

  1. 實例化(當咱們的程序加載beans.xml文件),把咱們的bean(前提是scope=singleton)實例化到內存中
  2. 調用set方法設置屬性,IOC注入
  3. 若是這個bean實現了BeanNameAware接口,會調用它實現的setBeanName(String beanId)方法,此處傳遞的是Spring配置文件中bean的ID
  4. 若是這個bean實現了BeanFactoryAware接口,會調用它實現的setBeanFactory(),傳遞是Spring工廠自己(能夠用這個方法取到其餘bean)
  5. 若是這個bean實現了ApplicationContextAware接口,會調用setApplicationContext(ApplicationContext)方法,傳入Spring上下文,該方式一樣能夠實現步驟4,但比4更好,由於ApplicationContext是BeanFactory的子接口,有更多的實現方法
  6. 若是這個bean關聯了BeanPostProcessor接口,將會調用postProcessBeforeInitialization(Object obj,String s)方法,BeanPostProcessor常常被用做是bean內容的更改,而且因爲這個是在bean初始化結束時調用After方法,也可用於內存或緩存技術
  7. 若是這個bean在spring配置文件中配置了init-method屬性,會自動調用其配置的初始化方法
  8. 若是這個bean關聯了BeanPostProcessor接口,將會調用postAfterInitialization(Object obj,String s)方法
  9. 使用bean
  10. 關閉bean
  11. 若是bean實現了DisposableBean接口,會調用其實現的destroy方法
  12. 若是這個bean的spring配置了destroy-method屬性,會自動調用其配置的銷燬方法

實際開發中,咱們每每沒用到這麼多的過程,常見的是:
實例化 => IOC注入 => AOP => 使用bean => 關閉bean

配置bean的細節

scope的說明:

做用域 描述
sigleton 在每一個Spring IoC容器中一個bean定義對應一個對象實例。
prototype 一個bean定義對應多個對象實例。
request 在一次HTTP請求中,一個bean定義對應一個實例;即每次HTTP請求將會有各自的bean實例,它們依據某個bean定義建立而成。該做用域僅在基於web的Spring ApplicationContext情形下有效。
session 在一個HTTP Session中,一個bean定義對應一個實例。該做用域僅在基於web的Spring ApplicationContext情形下有效。
global session 在一個全局的HTTP Session中,一個bean定義對應一個實例。典型狀況下,僅在使用portlet context的時候有效。該做用域僅在基於web的Spring ApplicationContext情形下有效。

儘可能使用scope="singleton",不要使用prototype,由於這樣對性能影響較大

4、如何給集合類型注入值

點我查看參考代碼文件夾
java中主要的集合有:map set list 數組
list:有序 能夠存儲相同的對象
set:無序 不能夠存儲相同對象 會覆蓋
Department類

package com.hsp.collection;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class Department {
    
    private String name;
    private String[] empName;
    private List<Employee> empList;
    private Set<Employee> empSets;
    private Map<String,Employee> empMaps;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String[] getEmpName() {
        return empName;
    }
    public void setEmpName(String[] empName) {
        this.empName = empName;
    }
    public List<Employee> getEmpList() {
        return empList;
    }
    public void setEmpList(List<Employee> empList) {
        this.empList = empList;
    }
    public Set<Employee> getEmpSets() {
        return empSets;
    }
    public void setEmpSets(Set<Employee> empSets) {
        this.empSets = empSets;
    }
    public Map<String, Employee> getEmpMaps() {
        return empMaps;
    }
    public void setEmpMaps(Map<String, Employee> empMaps) {
        this.empMaps = empMaps;
    }
    
}

Employee類

package com.hsp.collection;
public class Employee {
    private String name;
    private int id;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

beans.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="department" class="com.hsp.collection.Department">
    <property name="name" value="財務部"/>
    <!-- 給數組注值 -->
    <property name="empName">
        <list>
            <value>小明</value>
            <value>小小明</value>
            <value>大明</value>
        </list>
    </property>
    <!-- 給List注入值 ,list能夠有相同對象-->
    <property name="empList">
        <list>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
        </list>
    </property>
    <!-- 給set注入值 ,set不能有相同對象-->
    <property name="empSets">
        <set>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
            <ref bean="emp1"/>
            <ref bean="emp2"/>
        </set>
    </property>
    <!-- 給Map注入值,只要key不同,就能夠裝配value -->
    <property name="empMaps">
        <map>
            <entry key="1" value-ref="emp1"/>
            <entry key="2" value-ref="emp2"/>
        </map>
    </property>
</bean>

<bean id="emp1" class="com.hsp.collection.Employee">
    <property name="name" value="北京"/>
    <property name="id" value="1"/>
</bean>
<bean id="emp2" class="com.hsp.collection.Employee">
    <property name="name" value="天津"/>
    <property name="id" value="2"/>
</bean>
</beans>

內部bean

<bean id="foo" class="...Foo">
    <property name="屬性">
        <!-- 第一種方法引用 -->
        <ref bean="bean對象名" />
        <!-- 第二種內部bean -->
        <bean>
            <property name="屬性">
                ...
            </property>
        </bean>
    </property>
</bean>

5、繼承配置

點我查看參考代碼文件夾

public class Student
public class Graduate extends Student

在beans.xml中配置

<!-- 配置一個學生對象 -->
<bean id="student" class="com.hsp.inherit.Student">
    <property name="name" value="小明"/>
    <property name="age" value="20"/>
</bean>
<!-- 配置Graduate對象 --> 
<bean id="graduate" parent="student" class="com.hsp.inherit.Graduate">
    <!-- 若是本身配置屬性name,age,則會替換從父對象繼承的數據 -->
    <property name="name" value="大明"/>
    <property name="degree" value="學士"/>
</bean>

6、經過構造函數注入值

點我查看參考代碼文件夾
beans.xml關鍵代碼

<!-- 配置一個僱員對象 -->
<bean id="employee" class="com.hsp.constructor.Employee">
    <!-- 經過構造函數來注入屬性值 -->
    <constructor-arg index="0" type="java.lang.String" value="大明"/>
    <constructor-arg index="1" type="int" value="23"/>
</bean>

set注入的缺點是沒法清晰表達哪些屬性是必須的,哪些是可選的。
構造注入的優點是經過構造強制依賴關係,不可能實例化不徹底的或沒法使用的bean

7、自動裝配bean的屬性值 ==(重點)==

點我查看參考代碼文件夾

模式 說明
no 不使用自動裝配。必須經過ref元素指定依賴,這是默認設置。因爲顯式指定協做者可使配置更靈活、更清晰,所以對於較大的部署配置,推薦採用該設置。並且在某種程度上,它也是系統架構的一種文檔形式。
byName 不使用自動裝配不使用自動裝配。必須經過ref元素指定依賴,這是默認設置。因爲顯式指定協做者可使配置更靈活、更清晰,所以對於較大的部署配置,推薦採用該設置。並且在某種程度上,它也是系統架構的一種文檔形式。
byType 若是容器中存在一個與指定屬性類型相同的bean,那麼將與該屬性自動裝配。若是存在多個該類型的bean,那麼將會拋出異常,並指出不能使用byType方式進行自動裝配。若沒有找到相匹配的bean,則什麼事都不發生,屬性也不會被設置。若是你不但願這樣,那麼能夠經過設置dependency-check="objects"讓Spring拋出異常。
constructor 與byType的方式相似,不一樣之處在於它應用於構造器參數。若是在容器中沒有找到與構造器參數類型一致的bean,那麼將會拋出異常。
autodetect 經過bean類的自省機制(introspection)來決定是使用constructor仍是byType方式進行自動裝配。若是發現默認的構造器,那麼將使用byType方式。
  1. byName的用法
<!-- 配置一個master對象 -->
<bean id="master" class="com.hsp.autowire.Master" autowire="byName">
    <property name="name">
        <value>小明</value>
    </property>
</bean>
<!-- 配置一個dog對象 -->
<bean id="dog" class="com.hsp.autowire.Dog">
    <property name="name" value="大黃"/>
    <property name="age" value="3"/>
</bean>
  1. byType
    找和屬性類型相同的bean,找不到,裝不上,找到多個拋異常

  2. constructor
    查找和bean的構造參數一致的一個或多個bean,若找不到或找到多個,拋異常。按照參數的類型裝配

  3. autodetect
    (3)和(2)之間選一個方式。不肯定性的處理與(3)和(2)一致。

  4. defualt

==這個須要在 ==
當你在 指定了 default-atuowrite後, 全部的bean的默認的autowire就是 指定的裝配方法;
若是沒有在 沒有 defualt-autorwire=「指定」 ,則默認是
defualt-autorwire=」no」

autowire默認值是default。
default-autowire默認值是no

  1. no:不自動裝配
    使用spring的特殊bean,完成分散配置:

使用spring的特殊bean,完成分散配置

beans.xml

說明:當經過 context:property-placeholder 引入多個properties文件時,要用逗號隔開

<!-- 引入咱們的db.properties文件 -->           
<context:property-placeholder location="classpath:com/hsp/dispatch/db.properties,classpath:com/hsp/dispatch/db2.properties"/>  
<!-- 配置-DBUtil對象 -->
<bean id="dbutil1" class="com.hsp.dispatch.DBUtil">
    <property name="name" value="${name}" />
    <property name="driver" value="${driver}" />
    <property name="url" value="${url}" />
    <property name="pwd" value="${pwd}" />
</bean>
<!-- 配置-DBUtil對象 -->
<bean id="dbutil2" class="com.hsp.dispatch.DBUtil">
    <property name="name" value="${db2.name}" />
    <property name="driver" value="${db2.driver}" />
    <property name="url" value="${db2.url}" />
    <property name="pwd" value="${db2.pwd}" />
</bean>

db.properties

name=scott
driver=oracle:jdbc:driver:OraclaDriver
url=jdbc:oracle:@localhost:3306
pwd=123456

8、AOP編程

點我查看參考代碼文件夾

aop(aspect oriented programming):面向切面編程,是對全部對象或者是一類對象編程
核心:在==不==增長代碼的基礎上,==還==增長新的功能
  • 彙編(僞機器指令 mov jump) 面向機器
  • c語言(面向過程 )->系統軟件(操做系統,數據庫, 殺毒軟件,防火牆,驅動..)
語句1;
語句2;
...
  • java語法(面向對象->類-對象)
Class Dog {
    屬性;->變量
    行爲->函數
}
  • 面向切面 spring( ->aop) 面向n多對象編程
    aop特別提醒: aop編程,實際上在開發框架自己用的多,在實際項目中,用的不是不少,可是未來會愈來愈多,這個一個趨勢.

AOP原理 + 案例

步驟
  1. 定義接口
  2. 編寫對象(被代理對象 = 目標對象)
  3. 編寫通知(前置通知目標方法調用前調用)
  4. 在beans.xml文件配置
  • 配置 被代理對象 = 目標對象
  • 配置通知
  • 配置代理對象 是ProxyFactoryBean的對象實例
    ① <!-- 代理接口集 -->
    ② 織入通知
    ③ 配置被代理對象
    後面還有好後置通知、環繞通知、異常通知、引入通知

spring的aop中,當你經過代理對象去實現aop的時候,獲取的ProxyFactoryBean是什麼類型?
返回的是一個代理對象,若是目標對象實現了接口,則spring使用jdk 動態代理技術,若是目標對象沒有實現接口,則spring使用CGLIB技術.

資源地址:https://pan.baidu.com/s/1bpGVxgz, 提取密碼 m5fn

相關文章
相關標籤/搜索