天天看點

從javaweb入門到spring+mvc架構(一)——spring先來學習spring

由于怕過久了對于配置的一些原理和配置上的細節會忘記,是以記錄下來。

在學習完javase和javaweb的servlet部分知識後,就必須進入到架構的學習,架構可以減少很多繁瑣重複的工作量,提供更強大的功能。

先來學習spring

什麼是IOC

所謂控制反轉,就是把對其他對象的執行個體化和調用,轉給spring容器來做。

看下面代碼:

public class TestIOC {

    LoginService loginService = new LoginServiceImpl();

    loginService.doLogin("張三","123");

}
           

上面TestIOC類需要調用LoginService類,直接執行個體化它,這就等于LoginService 的控制在TestIOC手裡。

如果使用spring的IOC控制反轉,那麼代碼如下:

public class TestIOC {

    LoginService loginService;

    loginService.doLogin("張三","123");

}
           

這時候執行個體化過程被省略,因為需要的loginService這個執行個體是spring容器通過配置bean檔案在容器中執行個體化了,然後注入到LoginService這個接口成為它的執行個體對象。

是以new LoginServiceImpl()這個執行個體的建立的控制權就從業務邏輯的類中轉移到spring容器中,這就是控制反轉的意思。

IOC的好處就是能夠面向接口程式設計,減少類之間的耦合,這樣每個類都分子產品做自己的事情。同時可以把業務分成很多的子產品,然後使用容器來裝載這些子產品,使得它們共同工作,也友善靈活的添加需要的子產品bean和排除不需要的子產品bean。

什麼是AOP

aop即所謂面向切面程式設計,意思是把你的程式執行過程從上面和下面切開,同時把需要執行的附加内容插入到這個切面中:

public void 普通方法(){

        System.out.println("我是好人");

    }
           

如上,如果要在System.out.println(“我是好人”)之前加上判斷,在之後加上确認,如果沒有AOP隻能進入源碼中修改,就像下面這樣:

public void 普通方法(){

        doBeforeMethod();

        System.out.println("我是好人");

        doAfterMethod();

    }
           

但是使用AOP後可以把代碼切出兩個面,一個是在System.out.println(“我是好人”)之前,一個在之後,然後再在切面的位置添加需要的代碼即可,原來的代碼不變:

public void 普通方法(){

        System.out.println("我是好人");

    }

    public void useAOP(){

        切面:doBeforeMethod();

        調用那個普通方法的代碼...

        切面:doAfterMethod();

    }
           

從上面看到,普通方法本身不需要修改,隻需要在AOP中找到切面添加相應方法即可,效果就跟把代碼插進去一樣。

AOP的原理是使用反射,可以用在攔截器(在執行所有内容之前和之後給你執行下某些代碼)。也可以用在資料庫的事務管理中,簡單原理如下:

一個更新操作,需要開啟事務,執行更新,送出和復原三步:

public boolean update() {

        conn.setAutoCommit(false);
        try{

            conn.execute("更新");

            conn.commit();
        } catch(異常) {
            conn.rollback();
        }
    }
           

使用AOP的切面程式設計思想,把第一步的conn.setAutoCommit(false)和第三步的conn.commit()+conn.rollback()抽取出來,分别放到執行conn.execute(“更新”)之前和之後的兩個切面中,變成了:

public boolean update() {

        conn.execute("更新");

    }

    public boolean useAOP() {
        conn.setAutoCommit(false);
        try{

            調用那個更新方法的代碼...

            conn.commit();
        } catch(異常) {
            conn.rollback();
        }
    }
           

調用那個更新方法的代碼使用的是反射,我們發現update方法隻需要關注業務,事務的開啟和復原已經使用AOP思想配置在容器中了。這樣做的好處就是,如果有非常多個資料庫更新,插入等操作,事務管理的代碼都不用寫了,在容器中配置開啟就可以。

spring的如何初始化bean

一般是在路徑下配置的applicationContext.xml中配置好bean,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                        http://www.springframework.org/schema/context 
                        http://www.springframework.org/schema/context/spring-context-4.3.xsd 
                        http://www.springframework.org/schema/aop 
                        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    //看這個bean:
    <bean id="demoService" class="com.pack.DemoServiceImpl">

    </bean>

</beans>
           

上面我們在applicationContext.xml的中配置了一個,指定這個bean的id為demoService,具體的類為com.pack.DemoServiceImpl,那麼,ServletContextListener接口的實作類會在spring容器啟動(也就是啟動你的project app)的時候把applicationContext.xml中的所有bean初始化,如同上面IOC部分提到的一樣,不需要自己new一個類執行個體出來,容器會幫我們注入bean執行個體。

到此,有三個疑問沒有解決:

1、 spring容器 去哪裡 調用ServletContextListener接口的實作類

加載applicationContext.xml配置檔案需要注冊一個監聽器,這個監聽器需要實作ServletContextListener接口,其實隻要在我們熟悉的web.xml檔案中配置好:

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

ContextLoaderListener就是ServletContextListener接口的實作類,在spring-web.jar包内,spring容器就是根據web.xml中配置的ContextLoaderListener來加載applicationContext.xml配置檔案

2、 ServletContextListener接口的實作類 如何 加載applicationContext.xml

3、 加載之後如何執行個體化和管理bean

ContextLoaderListener會監聽啟動WebApplicationContext,WebApplicationContext會有一系列的動作包括擷取配置檔案applicationContext.xml的内容并且初始化bean等(具體實作不清楚),簡單原理大概如下。

String xmlPath = "WEB-INF\\applicationContext.xml";
    //擷取配置檔案的對象等
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    //獲得執行個體
    DemoService demoService = (DemoService)applicationContext.getBean("id");
           

繼續閱讀