Spring核心知識詳細教程

本文全文手寫,代碼全部手寫,也希望大家,可以做一遍,最起碼調試一遍,這樣比看的效果好的多,本文的spring使用的是5.0.4版本,ide使用的是IntelliJ IDEA,不足和錯誤之處還請大家指出,謝謝!!

一、spring是什麼

  • Spring是一個開放源代碼的設計層面框架,他解決的是業務邏輯層和其他各層的鬆耦合問題,因此它將面向接口的編程思想貫穿整個系統應用。Spring是於2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson創建。簡單來說,Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源框架

  • spring官網

  • spring百度百科
  • spring-framework

二、spring快速入門

  • 什麼是spring?

  • 首先我們瞭解到struts是web框架(jsp/action/actionform)
  • hibernate是 orm框架處於持久層
  • spring是容器框架,用於配置bean,並維護bean之間的關係的框架

  • spring中的bean:是一個很重要的概念,這裏的bean可以是Java中的任何一種對象:JavaBean/service/action/數據源/dao等等
  • spring中的ioc(inverse of control 控制反轉)
  • spring中的di(dependency injection 依賴注入)
    接下來看一個層次框架圖:
    這裏寫圖片描述
    說明:

  • web層: struts充當web層,接管jsp,action,表單,主要體現出mvc的數據輸入數據的處理數據的顯示分離
  • model層: model層在概念上可以理解爲包含了業務層,dao層,持久層,需要注意的是,一個項目中,不一定每一個層次都有
  • 持久層:體現oop,主要解決關係模型和對象模型之間的阻抗
  • 入門項目

    • 創建java項目(web中也可以使用)
    • 創建lib文件夾引入spring的開發最小包(最小配置,spring.jar(該包把最常用的包都包括),commons-logging.jar(日誌包))
    • 創建配置文件,一般在src目錄下
    • 配置bean
      這裏寫圖片描述
      說明:<bean></bean>這對標籤元素的作用:當我們加載spring框架時,spring就會自動創建一個bean對象,並放入內存相當於我們常規的new一個對象,而<property></property>中的value則是實現了“對象.set方法”,這裏也體現了注入了概念
    • 然後在java文件(測試文件)中調用

    接下來看具體的項目:
    這是我的目錄結構
    說明:這是我的目錄結構,其中我使用了ide整合了jar包,如果是手動創建時只需將jar包導入到項目裏即可

    User.java

    package com.nuc.Bean;
    
    public class User {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String sayHello(){
            System.out.println("hello"+ name);
            return "true";
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    拋開spring框架,使用傳統方式實現在測試類中調用sayHello方法:
    這裏寫圖片描述
    這樣,沒有異議吧。
    接下來使用spring調用該方法
    這裏寫圖片描述
    結果爲小強,是因爲上面的配置文件中配置value爲小強

    這樣一個基本的項目就完成了~
    接下來是細節:

    • 創建User2這個類

    package com.nuc.Bean;
    
    public class User2 {
        private String name;
    
        public String getName() {
            return name;
        }
    
       public void setName(String name) {
            this.name = name;
        }
        public void sayBye(){
            System.out.println("bye"+name);
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 在User中新增private User2 user2;並在sayHello中調用sayBye方法
    這裏寫圖片描述
  • 執行test類報出錯誤,這是由於user2未注入
    這裏寫圖片描述
  • 在配置文件中配置注入
    這裏寫圖片描述
    注意點細節都已經在圖中註釋表明
  • 再次運行測試類
    這裏寫圖片描述
    spring運行原理圖
    原理圖
    入門項目小結:
    spring實際上是容器框架,可以配置各種bean,並可以維護bean與bean的關係,當我們需要使用某個bean的時候,我們可以直接getBean(id),使用即可
  • 現在我們來回答什麼是spring這個問題

    • spring是一個容器框架,它可以接管web層,業務層,dao層,持久層的各個組件,並且可以配置各種bean, 並可以維護bean與bean的關係,當我們需要使用某個bean的時候,我們可以直接getBean(id),使用即可

    接下來對幾個重要的概念做說明:

    • ioc是什麼?
      • ioc(inverse of control)控制反轉:所謂反轉就是把創建對象(bean)和維護對象(bean)的關係的權利從程序轉移到spring的容器(spring-config.xml)
    • di是什麼?
      • di(dependency injection)依賴注入:實際上di和ioc是同一個概念,spring的設計者,認爲di更準確的表示spring的核心

    實質上學習框架就是,最重要的就是學習各個配置

    三、接口編程

    • spring就提倡接口編程,在配合di技術就可以達到層與層解耦的目的
    • 舉案例說明:
      這個項目實現的是大小寫轉換
      基本思路:

    • 創建一個接口
    • 創建兩個類實現接口
    • 配置bean
    • 使用

    下面是我的項目目錄
    這裏寫圖片描述

    ChangeLetter.java

    package com.nuc;
    
    public interface ChangeLetter {
        public String change();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    LowerLetter.java

    package com.nuc;
    
    public class LowerLetter implements ChangeLetter {
        private String str;
    
        public String getStr() {
            return str;
        }
    
        public void setStr(String str) {
            this.str = str;
        }
    
        public String change(){
            //大小字母轉小寫
            return str.toLowerCase();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    UpperLetter.java

    package com.nuc;
    
    public class UpperLetter implements ChangeLetter {
        private String str;
    
        public String getStr() {
            return str;
        }
    
        public void setStr(String str) {
            this.str = str;
        }
    
        public String change(){
            //把小寫字母轉成大寫
           return str.toUpperCase();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    spring-config.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="changeLetter" class="com.nuc.UpperLetter">-->
            <!--<property name="str">-->
                <!--<value>sjt</value>-->
            <!--</property>-->
        <!--</bean>-->
    
        <bean id="changeLetter" class="com.nuc.LowerLetter">
            <property name="str" value="SJT"/>
        </bean>
    </beans>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    說明:其中的兩個bean id名相同是爲了調試方便,可通過註釋來調試
    Test.java

    package com.nuc;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test {
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
            //調用change不使用接口
    //        UpperLetter changeLetter = (UpperLetter) ac.getBean("changeLetter");
    //        System.out.println(changeLetter.change());
    
            //使用接口
            ChangeLetter changeLetter = (ChangeLetter)ac.getBean("changeLetter");
            System.out.println(changeLetter.change());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    以上這個案例,我們可以初步體會到,di和接口編程,的確可以減少層(web層)和層(業務層)之間的耦合度,儘管看起來似乎沒什麼改變,而且好像麻煩了一些,但是當項目大了以後,這種耦合度的降低就顯得尤爲重要

    四、獲取Bean

    • ApplicationContext 應用上下文容器取

    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");

    當這句代碼被執行,spring-config.xml文件中配置的bean就會被實例化。(但要注意bean的生命週期要爲singleton),也就是說,不管沒有getBean(),使用上下文容器獲取bean,就會實例化該bean

  • Bean工廠容器取

  • BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

    這句代碼被執行,spring-config.xml文件中配置的bean不會被實例化,即光實例化容器,並不會實例化bean
    而是在執行以下代碼時纔會被實例化,即使用bean的時候
    factory.getBean("beanId");

    如何驗證上述說法呢?每一個java類都有一個默認的構造方法。給這個構造方法輸出一句話。具體如下

    • 創建一個類,類有一個屬性,裝配,該屬性
    • 重寫該類的構造方法,輸出bean被創建
    • 創建測試類,測試

    使用ApplicationContext應用上下文容器
    這裏寫圖片描述
    使用bean工廠
    這裏寫圖片描述
    可以看到,這一行代碼,並不能時bean實例化,接下來加factory.getBean(“student”);試試
    這裏寫圖片描述
    這樣就是bean實例化了

    那麼在實際開發中選擇哪種方式?

    在移動開發中,即項目運行在移動設備中使用BeanFactory(節約內存,所以,你想節約內存開發就是使用bean工廠,但速度會受影響),但大部分的項目都是使用ApplicationContext(可以提前加載,缺點是消耗一點內存)
    貼一張bean的生命週期圖:
    這裏寫圖片描述
    接下來我們驗證前兩種作用域:
    第一種
    這裏寫圖片描述
    結果
    這裏寫圖片描述
    可以看到stu1和stu2擁有相同的地址,接下來測試第二種
    這裏寫圖片描述
    這裏寫圖片描述
    測試結束!
    至於後三種是在web開發中纔有實際意義!

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

    • ClassPathXmlApplicationContext (從類路徑中加載)
      • 這個不在贅述,上面所有例子都是利用這種方式加載的
    • FileSystemXmlApplicationContext (從文件系統中加載)
      這裏寫圖片描述
      可以看到是沒有問題的,需要注意的是,文件路徑爲絕對路徑,且注意使用轉義符,直接使用“C:\sjt\idea\code\spring\spring-interface\src”,會報錯,需要將“\”轉義,但實際開發中應用不多,瞭解即可
    • XmlWebApplicationContext (從web系統中加載)
      • 這種方式,注意,在tomcat啓動時就會加載,此處不做說明,在web應用中說明

    六、再談Bean的生命週期

    • 生命週期是一個重點嗎?答案是肯定的!!

    • 不瞭解生命週期難道不能開發了嗎?那自然是可以的,但如果你想實現更加高級的功能,你不瞭解那可能是會出問題的!而在面試過程中也是經常提及的。
    • 接下里我們舉例子說明

    • 生命週期分爲以下幾步:

    • 1、實例化
      • 當我們加載sping-config.xml文件時,bean就會被實例化到內存(前提是scope=singleton)
    • 2、設置屬性值
      • 調用set方法設置屬性,前提是有對應的set方法
    • 3、如果你調用BeanNameAware的set’Bean’Name()方法
      • 這是個接口,該方法可以給出正在被調用的bean的id
    • 4、如果你調用BeanFactoryAware的setBeanFactory()方法
      • 這也是個接口,該方法可以傳遞beanFactory
    • 5、如果你調用了ApplicationContextAeare的setApplicationContext()方法
      • 同樣爲接口,該方法傳遞一個ApplicationContext
    • 6、BeanPostProcessor的預初始化方法Before
      • 這個東西很厲害了,可以叫做後置處理器,它不是接口,具體細節,代碼體現
    • 7、如果你調用了InitializingBean的afterPropertiesSet()方法
    • 8、調用自己的init方法,具體爲在bean中有一個屬性inin-method=”init”
    • 9、BeanPostProcessor的方法After
    • 10、使用bean,體現爲調用了sayHi()方法
    • 11、容器關閉
    • 12、可以實現DisposableBean接口的destory方法
    • 13、可以在調用自己的銷燬方法,類似於8

    實際開發過程中,並沒有這麼複雜,常見過程爲,1,2,6,9,10,11

    接下來看代碼
    目錄結構
    MyBeanPostProcessor.java

    package com.nuc.BeanLife;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    public class MyBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("第九步,postProcessAfterInitialization方法被調用");
            return null;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("第六步,postProcessBeforeInitialization方法被調用");
            System.out.println("第六步,"+bean+"被創建的時間爲"+new java.util.Date());
            /*
            在這裏,能做的事情可就不止上面的這麼簡單的一句輸出了,它還可以過濾每個對象的ip
            還可以給所有對象添加屬性或者函數,總之就是所有對象!
            其實,這裏體現了AOP編程的思想,AOP呢就是面向切成編程(針對所有對象編程)
             */
    
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    PersonService.java

    package com.nuc.BeanLife;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.*;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class PersonService implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
            System.out.println("第二步調用set方法");
        }
        public void sayHi(){
            System.out.println("第十步,hi"+ name);
        }
        public PersonService(){
            System.out.println("第一步,實例化bean");
        }
        @Override
        public void setBeanName(String arg0){
            //該方法可以給出正在被調用的bean的id
            System.out.println("第三步,setBeanName被調用,調用的id名爲:"+arg0);
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            //該方法可以傳遞beanFactory
            System.out.println("第四步,setBeanFactory被調用,beanFactory爲:"+beanFactory);
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            //該方法傳遞一個ApplicationContext
            System.out.println("第五步,調用setApplicationContext方法:"+applicationContext);
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("第七步,調用afterPropertiesSet()方法");
        }
        public void init(){
            System.out.println("第八步、調用我自己的init()方法");
        }
    
        @Override
        public void destroy() throws Exception {
            //關閉數據連接,socket,文件流,釋放資源
            //這個函數的打印你看不到,應爲
            System.out.println("第十步,銷燬方法(但不建議使用這種方式釋放資源)");
        }
        public void destory(){
    //        也看到不
            System.out.println("銷燬");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    Test.java

    package com.nuc.BeanLife;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test {
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
            PersonService person1= (PersonService) ac.getBean("personService");
            person1.sayHi();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    spring-config.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="personService" init-method="init" destroy-method="destroy" scope="singleton" class="com.nuc.BeanLife.PersonService">
            <property name="name" value="sjt"></property>
        </bean>
        <bean id="personService2" class="com.nuc.BeanLife.PersonService">
            <property name="name" value="sjt2"></property>
        </bean>
        <!--配置自己的後置處理器,優點類似filter-->
        <bean id="myBeanPostProcessor" class="com.nuc.BeanLife.MyBeanPostProcessor">
    
        </bean>
    </beans>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    測試結果

    417, 2018 4:57:26 下午 
    信息: Loading XML bean definitions from class path resource [spring-config.xml]
    第一步,實例化bean
    第二步調用set方法
    第三步,setBeanName被調用,調用的id名爲:personService
    第四步,setBeanFactory被調用,beanFactory爲:org.springframework.beans.factory.support.DefaultListableBeanFactory@ae13544: defining beans [personService,personService2,myBeanPostProcessor]; root of factory hierarchy
    第五步,調用setApplicationContext方法:org.springframework.context.support.ClassPathXmlApplicationContext@646d64ab: startup date [Tue Apr 17 16:57:26 CST 2018]; root of context hierarchy
    第六步,postProcessBeforeInitialization方法被調用
    第六步,com.nuc.BeanLife.PersonService@2e6a8155被創建的時間爲Tue Apr 17 16:57:27 CST 2018
    第七步,調用afterPropertiesSet()方法
    第八步、調用我自己的init()方法
    第九步,postProcessAfterInitialization方法被調用
    第一步,實例化bean
    第二步調用set方法
    第三步,setBeanName被調用,調用的id名爲:personService2
    第四步,setBeanFactory被調用,beanFactory爲:org.springframework.beans.factory.support.DefaultListableBeanFactory@ae13544: defining beans [personService,personService2,myBeanPostProcessor]; root of factory hierarchy
    第五步,調用setApplicationContext方法:org.springframework.context.support.ClassPathXmlApplicationContext@646d64ab: startup date [Tue Apr 17 16:57:26 CST 2018]; root of context hierarchy
    第六步,postProcessBeforeInitialization方法被調用
    第六步,com.nuc.BeanLife.PersonService@6221a451被創建的時間爲Tue Apr 17 16:57:27 CST 2018
    第七步,調用afterPropertiesSet()方法
    第九步,postProcessAfterInitialization方法被調用
    第十步,hisjt
    
    Process finished with exit code 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    動手做一遍是最好的選擇!!
    使用bean工廠獲取bean對象,生命週期是和上下文獲取的不一樣的,如下圖
    這裏寫圖片描述
    其中我只裝配了一個bean,可見執行步驟的短缺

    七、裝配Bean

    • 使用xml裝配

    • 上下文定義文件的根元素是<beans></beans>,有多個子元素<bean></bean>,每個<bean>元素定義了bean如何被裝配到spring容器中
    • 對子元素bean最基本的配置包括bean的ID和它的全稱類名
    • 對bean的scope裝配,默認情況下爲單例模式,具體情況上面已經說過,建議查看文檔,更加具體,儘量不要使用原型bean,即scope設置爲propotype,這樣子會對性能有較大的影響
    • bean的init-methodestory-method的書寫,在生命週期那一塊兒已經很清楚了,此處不再贅述,需要說明的是,可以通過註解的方式來配置,而不是在bean中使用init-metho和destory-method屬性
      這裏寫圖片描述

    • 注入集合類型的數據,例如,map,set,list,數組,Properties….

    • 接下來舉例子
      目錄結構:
      這裏寫圖片描述

    Department.java

    package com.nuc;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    public class Department {
        private String name;
        private String []empName;//這裏int的數組也可以注入成功
        private List<Employee> empList;
        private Map<String,Employee> empMap;
        private Properties pp;
    
        public Properties getPp() {
            return pp;
        }
    
        public void setPp(Properties pp) {
            this.pp = pp;
        }
    
        public Set<Employee> getEmpSet() {
            return empSet;
        }
    
        public void setEmpSet(Set<Employee> empSet) {
            this.empSet = empSet;
        }
    
        private Set<Employee> empSet;
        public List<Employee> getEmpList() {
            return empList;
        }
    
        public void setEmpList(List<Employee> empList) {
            this.empList = empList;
        }
    
        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 Map<String, Employee> getEmpMap() {
            return empMap;
        }
    
        public void setEmpMap(Map<String, Employee> empMap) {
            this.empMap = empMap;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    Employee.java

    package com.nuc;
    
    public class Employee {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Test.java

    package com.nuc;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Map.Entry;
    
    public class Test {
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
            Department department = (Department)ac.getBean("department");
            System.out.println(department.getName());
    //        取集合
            for(String empName:department.getEmpName()){
                System.out.println(empName);
            }
            System.out.println("取list...");
            for (Employee e:department.getEmpList()){
                System.out.println("name="+e.getName());
            }
            System.out.println("取set...");
            for (Employee e:department.getEmpSet()){
                System.out.println("name="+e.getName());
            }
            System.out.println("迭代器取map...");
            //1.迭代器
            Map<String,Employee> employeeMap = department.getEmpMap();
            Iterator iterator = employeeMap.keySet().iterator();
            while (iterator.hasNext()){
                String key = (String)iterator.next();
                Employee employee=employeeMap.get(key);
                System.out.println("key="+key+" "+ employee.getName());
            }
            System.out.println("entry取map...");
            //2.簡潔(建議使用這種方式)
            for (Entry<String,Employee> entry:department.getEmpMap().entrySet()){
                System.out.println(entry.getKey()+" "+entry.getValue().getName());
            }
        }
        System.out.println("通過properties取數據");
        Properties properties = department.getPp();
        for (Entry<Object,Object> entry:properties.entrySet()){
            System.out.println(entry.getKey().toString()+" "+entry.getValue());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    spring-config.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.nuc.Department">
            <property name="name" value="財務部"></property>
    
            <!--給數組注入-->
            <property name="empName">
                <list>
                    <value>小明</value>
                    <value>小花</value>
                </list>
            </property>
    
            <!--給list注入-->
            <!--list可以存放相同的對象,並當作不同對象輸出-->
            <property name="empList">
                <list>
                    <ref bean="employee1"></ref>
                    <ref bean="employee2"></ref>
                </list>
            </property>
    
            <!--給set注入-->
            <!--set集合不可以存放相同對象-->
            <property name="empSet">
                <set>
                    <ref bean="employee1"></ref>
                    <ref bean="employee2"></ref>
                </set>
            </property>
    
            <!--給map注入-->
            <!--輸出的對象取決於key值,key值不同,對象相同也可以打出-->
            <!--當key值相同時,對象相同或者不同都打出最後一個key所對應的對象-->
            <property name="empMap">
                <map>
                    <entry key="1" value-ref="employee1"></entry>
                    <entry key="2" value-ref="employee2"></entry>
                    <entry key="3" value-ref="employee2"></entry>
                </map>
            </property>
            <!--給屬性集合注入-->
            <property name="pp">
                <props>
                    <prop key="1">hello</prop>
                    <prop key="2">world</prop>
                </props>
            </property>
        </bean>
    
        <bean id="employee1" class="com.nuc.Employee">
            <property name="name" value="北京"></property>
        </bean>
        <bean id="employee2" class="com.nuc.Employee">
            <property name="name" value="太原"></property>
        </bean>
    </beans>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    測試結果:
    這裏寫圖片描述

    注意點,細節都已在代碼中註釋!

    • 內部bean
      • 具體自行了解,實際中應用不多,不符合重用度高的原則
    • 繼承配置bean
      • 舉例說明:
        結構圖:
        這裏寫圖片描述
        Student.java
    package com.nuc.inherit;
    
    public class Student {
        protected String name;
        protected int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    Gradate.java

    package com.nuc.inherit;
    
    public class Gradate extends Student {
        private String degree;
    
        public String getDegree() {
            return degree;
        }
    
        public void setDegree(String degree) {
            this.degree = degree;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    spring-config.java

    <?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="student" class="com.nuc.inherit.Student">
            <property name="name" value="sjt"></property>
            <property name="age" value="22"></property>
        </bean>
        <!--配置gradate對象-->
        <bean id="gradate" parent="student" class="com.nuc.inherit.Gradate">
            <!--如果子類重新賦值,則覆蓋父類的-->
            <property name="name" value="小明"></property>
            <property name="degree" value="博士"></property>
        </bean>
    </beans>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Test2.java

    package com.nuc.inherit;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test2 {
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("com/nuc/inherit/spring-config.xml");
            Gradate gradate = (Gradate) ac.getBean("gradate");
            System.out.println(gradate.getName()+" "+gradate.getAge()+" "+gradate.getDegree());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 以上我們都是用set注入依賴的,下面介紹構造函數注入依賴
    <bean name="user" class="com.nuc.Bean.User">
        <!--通過constructor-arg標籤完成了對構造方法的傳參-->
        <!--如果是屬性是類類型,則使用ref=""-->
        <constructor-arg index="0" type="java.lang.String" value="小強"></constructor-arg>
        <constructor-arg index="1" type="java.lang.String" value="男"></constructor-arg>
        <constructor-arg index="2" type="int" value="20"></constructor-arg>
    </bean>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    當然對應的User要有相應的構造方法。
    set注入的缺點是無法清晰的表達哪個屬性是必須的,哪些是可選的,構造器注入的優勢,是可以通過構造強制依賴關係,不可能實例化不完全或者不能使用的bean

    但其實實際開發中還是set注入較多,即property注入

    • bean的自動裝配:
      這裏寫圖片描述
      接下來是實例:
      目錄圖
      這裏寫圖片描述
      Dog.java
    package com.nuc.autowire;
    
    public class Dog {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    Master.java

    package com.nuc.autowire;
    
    public class Master {
        private String name;
        private Dog dog;
    
        private Master(Dog dog){
            //爲了自動裝配的constructor
            this.dog= dog;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Dog getDog() {
            return dog;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    Test.java

    package com.nuc.autowire;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test {
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("com\\nuc\\autowire\\beans.xml");
            Master master = (Master)ac.getBean("master");
            System.out.println(master.getName()+"養了只狗,它的名字叫"+ master.getDog().getName()+",他今年"+master.getDog().getAge()+"歲了");
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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">
        <!--配置master對象-->
        <bean id="master" class="com.nuc.autowire.Master" autowire="constructor">
            <property name="name" value="sjt"></property>
            <!--傳統方式-->
            <!--<property name="dog" ref="dog"></property>-->
        </bean>
    
        <!--配置dog對象,byName時使用-->
        <!--<bean id="dog" class="com.nuc.autowire.Dog">-->
            <!--<property name="name" value="小黃"></property>-->
            <!--<property name="age" value="2"></property>-->
        <!--</bean>-->
    
        <!--配置dog對象,byType時使用-->
        <!--<bean id="dog11" class="com.nuc.autowire.Dog">-->
            <!--<property name="name" value="小黃"></property>-->
            <!--<property name="age" value="2"></property>-->
        <!--</bean>-->
    
        <!--配置dog對象,constructor時使用-->
        <bean id="dog22" class="com.nuc.autowire.Dog">
            <property name="name" value="小黃"></property>
            <property name="age" value="2"></property>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • autodetect:是在constructor和byType之間選一種
    • default:這種方式在文檔中沒有提及,需要在beans中指定,當你在beans中指定以後,所有的bean都是你所指定的裝配方式,如果沒有指定,則默認爲no,所以,no之所以爲默認指定裝配方式,其實是從beans那裏來的
      這裏寫圖片描述
      其實在實際開發中,很少用到自動裝配, 一般都是手動set裝配的(property),而且自動裝配也是在bean中沒有配置才取執行自動裝配的

    • spring本身提供的bean
      • 分散配置

    八、AOP編程(難點)

    • aop:aspect oriented programming(面向切面編程),它是對一類對象或所有對象編程。

    • 核心:在不增加代碼的基礎上,還增加新功能
    • 提醒:aop編程,實際上是開發框架本身用的多,開發中不是很多,將來會很多
    • 初步理解:面向切面:其實是,把一些公共的“東西”拿出來,比如說,事務,安全,日誌,這些方面,如果你用的到,你就引入。

    接下來通過例子來理解這個抽象的概念,概念稍後再說

    步驟:
    拿前置通知打比方,後來還會有,後置通知,環繞通知,異常通知,引入通知

    • 定義接口
    • 編寫對象(被代理對象=目標對象)
    • 編寫通知(前置通知目標方法調用前調用)
    • 在beans.xml中配置
      • 配置被代理對象
      • 配置通知
      • 配置代理對象(是proxyFactoryBean的對象實例)
        • 配置代理接口集
        • 織入通知
        • 配置被代理對象

    接下來看代碼:
    目錄結構:
    這裏寫圖片描述
    TestServiceInter.java(interface)

    package com.nuc.Aop;
    
    public interface TestServiceInter {
        public void sayHello();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    TestServiceInter2.java(interface)

    package com.nuc.Aop;
    
    public interface TestServiceInter2 {
        public void sayBye();
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    TestService.java

    package com.nuc.Aop;
    
    public class TestService implements TestServiceInter,TestServiceInter2{
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void sayHello(){
            System.out.println("hi "+name);
        }
    
        @Override
        public void sayBye() {
            System.out.println("bye "+name);
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    MyMethodBeforeAdvice.java

    package com.nuc.Aop;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
        //前置通知
        @Override
        public void before(Method method, Object[] objects, Object o)
                throws Throwable {
            //method:被調用方法的名字
            //objects:給method傳遞的參數
            //o:目標對象
            System.out.println("記錄日誌。。。"+method.getName());
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    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="testService" class="com.nuc.Aop.TestService">
            <property name="name" value="sjt"/>
        </bean>
        <!--配置前置通知-->
        <bean id="myMethodBeforeAdvice" class="com.nuc.Aop.MyMethodBeforeAdvice"></bean>
        <!--配置代理對象-->
        <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!--配置代理接口-->
            <property name="proxyInterfaces">
                <list>
                    <value>com.nuc.Aop.TestServiceInter</value>
                    <value>com.nuc.Aop.TestServiceInter2</value>
                </list>
            </property>
            <!--把通知織入到代理對象-->
            <property name="interceptorNames">
                <!--相當於把myMethodBeforeAdvice前置通知和代理對象關聯起來-->
                <value>myMethodBeforeAdvice</value>
            </property>
            <!--配置被代理對象,可以指定-->
            <property name="target" ref="testService"></property>
        </bean>
    </beans>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    Test.java

    package com.nuc.Aop;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test {
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("com/nuc/Aop/beans.xml");
            TestServiceInter testService = (TestServiceInter)ac.getBean("proxyFactoryBean");
            testService.sayHello();
            //當一個類繼承多個接口,那麼他們之間可以互轉
            ((TestServiceInter2)testService).sayBye();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    測試結果
    這裏寫圖片描述

    • AOP的術語

    • 切面:要實現交叉功能,是系統模塊化的一個切面領域,如記錄日誌
    • 連接點:應用程序執行過程中插入切面的地點,可以是方法調用,異常拋出,或者要修改的字段
      • 連接點是一個靜態的概念
    • 通知: 切面的實際實現,它通知系統的新行爲,如日誌通知包含了實現日誌功能的代碼,如向日志文件寫日誌,通知在連接點插入應用系統中。
    • 切入點:定義了通知應該應用在哪些連接點通知可以應用到AOP框架支持的任何連接點
      • 切入點是動態概念,當通知應用了連接點,連接點就變成了切入點
    • 引入:爲類添加新方法和屬性
    • 目標對象:通知的對象,既可以是你編寫的類,也可以是第三方類
    • 代理:通知應用到目標對象後創建後的對象,應用系統的其他部分不用爲了支持代理對象而改變
      • spring的兩種代理:
        • 目標對象實現了若干個接口,spring使用JDK的java.lang.reflect.Proxy類代理
        • 目標對象沒有實現任何接口,spring使用CGLIB庫生成目標對象的子類
    • 織入:切面應用到目標對象從而創建一個新代理對象的過程,織入發生在目標對象生命週期的多個點上
      • 編譯期:切面在目標對象編譯時織入,這需要一個特使的編譯器
      • 類裝載期:切面在目標對象被載入jvm時織入,這需要一個特殊的類加載器
      • 運行期:切面在應用系統運行時切入

    接下來引入後置通知,環繞通知,異常通知,引用通知

    類似於前置通知,前三者需要繼承一種接口,引用通知直接配置

    MyAfterReturningAdvice.java

    package com.nuc.Aop;
    
    import org.springframework.aop.AfterReturningAdvice;
    
    import java.lang.reflect.Method;
    
    public class MyAfterReturningAdvice implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object o, Method method, Object[] objects,
                                   Object o1)
                throws Throwable {
            //後置通知
            //o:前面函數的返回值
            //method:哪個方法被調用
            //objects:調用方法的參數
            //o1:目標對象
            System.out.println("後置通知:調用結束,關閉資源。");
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    MyMethodInterceptor.java

    package com.nuc.Aop;
    
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    
    public class MyMethodInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            //環繞通知
            System.out.println("環繞通知:進入函數體,調用方法前");
            Object obj = methodInvocation.proceed();
            System.out.println("環繞通知:完成調用");
            return obj;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    MyThrowsAdvice.java

    package com.nuc.Aop;
    
    import org.springframework.aop.ThrowsAdvice;
    
    import java.lang.reflect.Method;
    
    public class MyThrowsAdvice implements ThrowsAdvice {
        //異常通知
        //ThrowsAdvice這個接口是標識性接口,沒有任何方法
       public void afterThrowing(Method m,Object[] os,Object target,Exception e){
            System.out.println("異常通知:出問題了:"+e.getMessage());
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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="testService" class="com.nuc.Aop.TestService">
            <property name="name" value="sjt"/>
        </bean>
        <!--配置前置通知-->
        <bean id="myMethodBeforeAdvice" class="com.nuc.Aop.MyMethodBeforeAdvice"></bean>
        <!--配置後置通知-->
        <bean id="myAfterReturningAdvice" class="com.nuc.Aop.MyAfterReturningAdvice"></bean>
        <!--配置環繞通知-->
        <bean id="myMethodInterceptor" class="com.nuc.Aop.MyMethodInterceptor"></bean>
        <!--配置異常通知-->
        <bean id="myThrowsAdvice" class="com.nuc.Aop.MyThrowsAdvice"></bean>
        <!--定義前置通知的切入點(引用通知)-->
        <bean id="myMethodBeforeAdviceFilter" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <property name="advice" ref="myMethodBeforeAdvice"></property>
            <property name="mappedNames">
                <list>
                    <!--這裏支持使用正則表達式匹配-->
                    <!--配置了sayHello使用前置通知過濾-->
                    <value>sayHello</value>
                </list>
            </property>
        </bean>
        <!--配置代理對象-->
        <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!--配置代理接口-->
            <property name="proxyInterfaces">
                <list>
                    <value>com.nuc.Aop.TestServiceInter</value>
                    <value>com.nuc.Aop.TestServiceInter2</value>
                </list>
            </property>
            <!--把通知織入到代理對象-->
            <property name="interceptorNames">
                <list>
                    <!--相當於把myMethodBeforeAdvice前置通知和代理對象關聯起來-->
                    <!--使用自定義切入點-->
                    <value>myMethodBeforeAdviceFilter</value>
                    <!--織入後置通知-->
                    <value>myAfterReturningAdvice</value>
                    <!--織入環繞通知-->
                    <value>myMethodInterceptor</value>
                    <!--織入異常通知-->
                    <value>myThrowsAdvice</value>
                </list>
            </property>
            <!--配置被代理對象,可以指定-->
            <property name="target" ref="testService"></property>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    TestService.java
    這裏寫圖片描述
    如圖這一處變動
    總之呢就是一個配置 -> 織入的過程
    運行結果:
    這裏寫圖片描述
    可以看到前置通知和後置通知,似乎能夠識別方法,事實上也是這樣的(spring框架內置)。而且sayBay()也得到了應用。這正是,我們前面所提到了,AOP是對一類或所有對象編程的體現,又由於異常通知的配置,有了異常,由於引用通知的配置,致使sayBay的前置通知及後續無法通知。
    正常結果(配置引用通知):
    這裏寫圖片描述

    總結

    spring框架呢,其實就是學習了一大堆的配置,還有幾個spring比較新穎的“思想”,IOC,AOP,這些技術。主要還是spring-config.xml文件的配置,之所以後來改成beans,是因爲,這個文件就是對bean的配置!這套教程,是根據韓老師的視頻總結的,全文基本都是要點,沒有水貨。。。(自我認爲),因爲韓老師將的很到位,很深刻,所以教程自然差不了

    爲時5天的總結就結束了。筆者後期還會推出springMVC,Hibernate,望支持~

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章