SSM框架之--spring(一)

一、why–爲什麼用spring?

1.spring框架爲我們提供了很多現成的功能(IoC、AOP、聲明式事務等、SpringMVC等),這些功能可以直接拿來用、提高開發效率。
2.進一步提高軟件產品的質量
框架是前人對軟件開發經驗的總結,相當於站在巨人的肩膀上,讓一個普通的程序員也能寫出高質量的軟件成品(符合軟件工程的規範,例如高內聚 低耦合、OCP等)

不用框架 做小的項目沒問題,但是做大的項目就需要框架做強大的支撐,這一點從MyBatis就可以看出來,如果不用MyBatis,用JDBC做項目太繁瑣了。

二、what–spring是什麼?

Spring 春天 心情好了 軟件質量高了 工資高了 需求變了 不需要改代碼 不需要加班了

MyBatis、Hibernate 優秀的持久化層解決方案 當今主流的ORMapping工具

SpringMVC、Struts MVC框架 代替servlet

Spring 綜合型框架(一站式服務) 管理層框架

綜合型框架(功能很多 涉及到Java EE各層)

管理層框架(javaEE各層 po dao service action 大家長 不管你 軟件質量得不到保證)

從spring的四個大的方面講解一下spring
這裏寫圖片描述

1.IOC容器

Inversion Of Control 控制反轉

2.對持久層支持(DAO ORM)

簡化hibernate開發(簡化jdbc開發)
聲明式事務

3.web層集成(控制器 jsp)

自己的MVC框架 spring mvc

整合web層框架 struts1 、struts2、WebWork、JSF等

4.AOP

Aspect Oriented Programming 面向切面編程

切面說白了就是一個類 可以給任何方法前面或後面加方法 攔截器就是一個切面 思想就是AOP思想

5.JEE支持

JMS即Java消息服務(Java Message Service)

JCA (J2EE 連接器架構,Java Connector Architecture): 用來連接非java語言編寫的系統.

Remoting 遠程方法調用

EJBs 企業級javaBean 處理分佈式業務

Email 郵件

JMX(Java Management Extensions,即Java管理擴展)

三、IOC容器(核心功能)

IOC Inversion Of Control 控制反轉

什麼是容器

1.集合 list

2.tomcat jsp/servlet容器 只管理jsp servlet對象生命週期(從創建到銷燬)

3.spring IOC容器能管理所有對象的週期(從創建到銷燬 對象的存取)

爲什麼要使用IOC容器(IOC容器的好處)

1.解耦 (徹底實現OCP)
2.Inversion Of Control 控制反轉
3.單例

1.IOC容器的好處之解耦(徹底實現OCP)

解耦(使用接口) 緊密耦合(筆記本和屏幕)——->鬆散耦合(PC)

緊耦合壞處:需求變了 需要改代碼

演示筆記本運行例子(相當於自己實現spring的IOC功能)

import java.io.BufferedReader;
import java.io.FileReader;

public class Test {
public static void main(String[] args) throws Exception{

    //從文件中讀進來
    //1.建立通道
    FileReader fr = new FileReader("c:\\spring.txt");

    BufferedReader br = new BufferedReader(fr);

    String screenClassName = br.readLine();

    //Screen screen = new RetinaScreen14();

    Class<?> clazz = Class.forName(screenClassName);
    Screen screen = (Screen)clazz.newInstance();

    //改成反射的
    Notebook notebook = new Notebook();
    notebook.setScreen(screen);

    notebook.work();
}   

}

爲了讓筆記本和具體的屏幕類解耦,不依賴於具體的屏幕類,緊耦合–>鬆散耦合,提高軟件質量,不用改代碼,可維護,要寫這麼多代碼,這麼麻煩???

我也不會怎麼辦???

使用spring啊

四、如何使用spring?

http://maven.springframework.org/release/org/springframework/spring/

Spring3.2.4

1.導jar包

spring-core-3.2.4.RELEASE.jar
spring-beans-3.2.4.RELEASE.jar
spring-context-3.2.4.RELEASE.jar
spring-expression-3.2.4.RELEASE.jar

commons-logging-1.1.1.jar spring依賴於這個日誌包

注:老版本的spring有一個整合包spring.jar,也有分開的,新版的沒有整合包,都是分開的,分開的目的是便於按需引入.

2.定義類和接口

public interface IScreen {
public void display();
}

public class Screen14 implements IScreen{

public Screen14(){
    System.out.println("創建了Screen14對象");
}

public void display(){
    System.out.println("使用14寸屏幕進行顯示");
}

}

public class RetinaScreen14 implements IScreen{

public RetinaScreen14(){
    System.out.println("創建了RetinaScreen14對象");
}

public void display(){
    System.out.println("使用14寸高分屏顯示");
}

}

public class Notebook {

private String pinpai;

private IScreen screen;

public Notebook(){
    System.out.println("創建了Notebook對象");
}

public void setScreen(IScreen screen){
    System.out.println("調用了setScreen方法  設置屏幕");
    this.screen = screen;
}


public String getPinpai() {
    return pinpai;
}


public void setPinpai(String pinpai) {
    System.out.println("調用setPinpai 設置品牌");
    this.pinpai = pinpai;
}

public IScreen getScreen() {
    return screen;
}

public void work(){

    screen.display();

}

}

3.配置文件

applicationContext.xml java工程放到src下 相當於classes (Web工程稍後再說)

<?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-2.0.xsd">


    <!-- 使用反射創建對象 -->
    <!--Screen14 screen14 = new Screen14();-->
    <bean id="screen14" class="com.test.Screen14"/>


    <!--Notebook notebook = new Notebook();-->
    <bean id="notebook" class="com.test.Notebook">
        <!-- 
            notebook.setPinpai("聯想");
            notebook.setScreen(screen14);
         -->
        <property name="pinpai" value="聯想"/>
        <property name="screen" ref="screen14"/>
    </bean>
</beans>

4.測試類

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

    public static void main(String[] args) {

        //獲得spring IOC容器
        //創建對象、設置依賴關係
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //從容器中取id爲notebook的對象
        Notebook notebook = (Notebook)context.getBean("notebook");

        notebook.work();
    } 
}

IOC控制反轉

Inversion of Control 控制翻轉
控制權的反轉 什麼控制權?

主要體現在兩點上

1.創建對象的控制權

由程序員 反轉給了spring完成
2.設置依賴關係的控制權利(重點)

本來是程序員 notebook.setScreen(screen14);

現在交給了spring完成

好處:
1.不用new 和 set了省事了(框架幫你完成了)

2.解耦(徹底實現OCP)

3.符合現實生活:

現實生活中來說用戶想使用筆記本,只要打開筆記本就可以了,沒必要先自己造一個筆記本,再造個屏幕,組裝起來?這樣用戶不是累死了?(關注的太多)
用戶只要關注具體的業務邏輯(讓筆記本工作)就可以了,其他的都交給spring來替
你完成(相當於筆記本是用來從spring工廠買過來的)。這樣用戶就從非業務邏輯(創建對象、設置依賴關係)的代碼中解脫出來。

DI:Denpendency Injection 依賴注入

控制反轉這個名詞不太形象,所以spring又換了一種更加形象的解釋,叫DI,其實是一個思想,只是DI更好理解罷了。

依賴注入

依賴關係,是spring給你注入的(設置的)

筆記本依賴於哪個屏幕類的對象 是spring幫你完成的,spring相當於對象的粘合劑

依賴注入的兩種方式:

一、setter注入 (推薦使用)

使用set方法給筆記本的屏幕初始化,告訴筆記本運行時到底依賴於哪個屏幕 Screen14 還是 RetinaScreen14

兩步
1.給筆記本的屏幕屬性 添加setter方法

public class Notebook{

private Screen screen;


public void setScreen(Screen screen){
    System.out.println("使用setScreen方法把屏幕組裝到筆記本中");
    this.screen = screen;
}

}

2.修改applicationContext.xml

    <bean id="screen14" class="com.test.Screen14"/>

    <bean id="retinaScreen14" class="com.test.RetinaScreen14"/>

    <bean id="notebook" class="com.test.Notebook">

        <!-- setter注入  notebook.setScreen(retinaScreen14)-- >
        <property name="screen" ref="retinaScreen14"/>
    </bean>

類的屬性是 基本類型和String 使用value

類的屬性是引用類型 使用ref reference 引用

注入集合的情況自己看 注入的兩種方式.txt

二.構造器注入

使用構造函數給 筆記本的屏幕進行初始化,設置筆記本和屏幕的依賴關係。

  1. 定義Notebook
    package com.ioc;

public class Notebook {

private String pinPai;
private Screen screen;

public Notebook() {
    System.out.println("創建了Notebook對象");
}


public Notebook(String pinPai, Screen screen) {

System.out.println(“使用兩個參數的構造函數(String pinPai, Screen screen)創建Notebook對象”);
this.pinPai = pinPai;
this.screen = screen;
}

public void work(){
    screen.display();
}

}

2.給筆記本添加相應的構造器

public Notebook(String pinPai, Screen screen) {

System.out.println(“使用兩個參數的構造函數(String pinPai, Screen screen)創建Notebook對象”);
this.pinPai = pinPai;
this.screen = screen;
}

3修改applicationContext.xml

<bean id="screen14" class="com.ioc.Screen14"/>

<bean id="retinaScreen14" class="com.ioc.RetinaScreen14"/>

 <!--Notebook notebook = new Notebook(“IBM”,retinaScreen14)-->
<bean id="notebook" class="com.ioc.Notebook">
    <constructor-arg value="IBM"/>
    <constructor-arg ref="retinaScreen14"/>
</bean>

如果有兩個同類型的參數,例如兩個String類型的參數,spring框架會按照構造函數中的順序設置,可以給電腦加一個productNo產品編號 屬性演示

public Notebook(String productNo, String pinPai, Screen screen) {
System.out.println(“使用3個參數的構造函數創建Notebook對象”);
this.productNo = productNo;
this.pinPai = pinPai;
this.screen = screen;
}


<bean id="notebook" class="com.ioc.Notebook">
        <constructor-arg value="1"/>
        <constructor-arg value="IBM"/>
        <constructor-arg ref="retinaScreen14"/>
    </bean>

控制檯打印

如果把配置文件中的constructor調換順序

<bean id="notebook" class="com.ioc.Notebook">
        <constructor-arg value="IBM"/>
        <constructor-arg value="1"/>
        <constructor-arg ref="retinaScreen14"/>
</bean>

可以通過設置index值標示給第幾個參數傳值,index=0表示給構造函數中的第一個參數傳參,index=1表示給第二個參數傳參.如果不寫index,默認第一個參數index=0,依次類推

配置文件如下

<bean id="screen14" class="com.ioc.Screen14"/>

    <bean id="retinaScreen14" class="com.ioc.RetinaScreen14"/>

    <bean id="notebook" class="com.ioc.Notebook">
        <constructor-arg value="IBM" index="1"/>
        <constructor-arg value="1" index="0"/>
        <constructor-arg ref="retinaScreen14" index="2"/>
    </bean>

IOC容器的好處 之 單例


  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("*********************************");    
  Notebook notebook = (Notebook)context.getBean("notebook");
  Notebook notebook2 = (Notebook)context.getBean("notebook");

  System.out.println(notebook==notebook2);//true 證明兩次獲得的是同一個對象
  notebook.work();


注意:兩次得到的是一個對象 getBean方法只是在容器裏取出一開始創建的對象而已,並沒有創建對象,創建對象由第一句完成

如果想每次都創建一個新的對象,怎麼辦??


<bean id="notebook" class="com.ioc.Notebook" scope="prototype">
        <constructor-arg value="1"/>
        <constructor-arg value="IBM"/>
        <constructor-arg ref="retinaScreen14"/>
</bean>

一句話總結
IOC容器除了是一個普通容器外,主要解決了統一管理對象生命週期、解耦合、維護依賴關係,以及應用程序對單例的大量需要等問題。

五.自動裝配和依賴檢查

自動裝配:就是程序員不用顯示的使用 給筆記本設置一個屏幕,設置屏幕的
工作交給spring自動完成就可以了,只需要在需要使用自動裝配功能的 節點上加入 autowire屬性即可

autoware:no(默認值) 不自動裝配
autoware:byType 按照類型自動裝配,spring正好找到一個就裝配,如果找到兩個或兩個以上類型相同的,就報錯.沒有找到就不裝配
autoware:byName 按照名字自動裝配

也可以定義到beans節點上
這樣所有的bean都是按名稱自動裝配了

雖然說自動裝配它減少了配置文件的工作量,但是程序員不知道到底裝配了什麼,降低了依賴關係的清晰性,所以不推薦使用

依賴檢查:spring框架幫你檢查bean的屬性是否都初始化

dependency-check=”default/none/simple/objects/all”

default 表示繼承beans的,父節點beans的默認值none 不檢查

simple類型:檢查基本類型、包裝類型和String、集合有沒有初始化,沒初始化就報錯

objects: 只檢查引用類型有沒有初始化

All: 基本類型和引用類型都幫你檢查一下有沒有初始化

注意:依賴檢查的時候要爲需要檢查的屬性設置setters方法 否則即使在配置文件中配置了依賴檢查,spring也不會幫你進行依賴檢查

六、在web應用程序中使用spring

如果想把spring用在web應用程序上,只需要修改三步

1.把applicationContext.xml放到WEB-INF下

2.另外導入一個jar包spring-web-3.2.4.RELEASE.jar

3.在web.xml中配置一個監聽器 ContextLoaderListener

<listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>

public class ContextLoaderListener extends ContextLoader implements ServletContextListener

配置完畢後啓動tomcat

控制檯顯示
創建了RetinaScreen14對象
創建了一個Screen14的對象
創建了一個Notebook對象
使用setScreen方法 把屏幕裝到筆記本里

相當於服務器一啓動
ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
執行了

啓動時ContextLoaderListener 讀取applicationContext.xml 創建了對象 並設置好對象之間的依賴關係

注意:
如果把文件放到WEB-INF下,使用下面語句就無法找到applicationContext.xml了,因爲這句話是從src下找

ApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);

這樣如果想測試程序,讀取WEB-INF下的applicationContext.xml就必須啓動web應用,比較麻煩,爲了方便測試

可以使用

ApplicationContext context = new FileSystemXmlApplicationContext(“WebRoot/WEB-INF/applicationContext.xml”);

這樣就可以在Test測試類中運行程序了,而不需要啓動web應用

這裏寫圖片描述

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