11 months ago

What is Spring ?

Spring是一個lightweight(輕量級)的framework(框架),它可以想像是各種框架的集成,因為它可以支援許多種框架,例如Struts, Hibernate, Tapestry, EJB, JSF等等,它包含幾種模組,例如IOC, AOP, DAO, Context, ORM, WEB MVC等等,不過我們第一步需要先了解IOC(控制反轉)以及Dependency Injection(依賴注入)。

What is IOC、Dependency Injection ?

Spring容器實現了IOC,也是這整個框架的核心所在,容器將會創建、管理物件直到銷毀,並使用Dependency Injection(依賴注入)來管理這些物件(Bean),然而Spring提供這兩種IOC容器,分別為BeanFactory、ApplicationContext,這兩部分的差別,後將依序簡單的探討。

BeanFactory
這是Spring提供最簡單的IOC容器,是無法使用大部分模組的,例如AOP、Integration、Web等等,因此僅適合在有限資源的環境下使用,通常用於測試與非生產環境。

ApplicationContext
大神也推薦使用這個IOC容器,該容器繼承BeanFactory並提供了更多的功能,因此我們可以方便的使用各種模組,來幫助開發。

Hello Spring

上面稍微介紹了Spring的核心功能,那麼我們現在來給它實作看看,應該會更加了解Spring容器。

目錄架構

Gradle

Gradle這邊我們只要引入spring-context即可,這個lib是Spring的核心,其他引入的部分並沒有使用到,只是我直接copy其他部分的程式碼XD。

apply plugin: 'java'
apply plugin: 'eclipse'

sourceCompatibility = 1.8
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart',
                   'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    //Spring

    def springVersion = '4.1.6.RELEASE'
    compile group: 'org.springframework', name: 'spring-context', version: "${springVersion}"
    
    //Log4j 2

    def log4jVersion = '2.8.2'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: "${log4jVersion}"
    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: "${log4jVersion}"
    compile group: 'org.apache.logging.log4j', name: 'log4j-jcl', version: "${log4jVersion}"

    //common

    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'

    //test

    testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
    systemProperties 'property': 'value'
}

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

beans.xml

Spring最經典的就是使用xml設定了,那麼其實有另外一種JavaConfig設定方式,我還在考慮要不要放XDD

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" 
  "http://www.springframework.org/dtd/spring-beans.dtd"> 
<beans> 
    <bean id="helloBean" class="com.spring.example.HelloSpringBean"> 
        <property name="message">
            <value>Hello Spring!!</value>
        </property> 
    </bean> 
</beans>

HelloSpringBean.java

這邊大家可以對應到上面的XML設定,會發現我們設定了class位置,並命名id為helloBean以及設定message為Hello Spring!!,然而這邊提醒一下,大家還是要習慣加入toString,會比較方便測試。

public class HelloSpringBean {

    private String message;
    
    public void setMessage(String message) {
        this.message = message;
    }
    
    public String getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "HelloSpringBean [message=" + message + "]";
    }
    
}

HelloSpringApp.java

這裡就是整個Spring容器啟動的時候,我們可以看到我使用了ClassPathXmlApplicationContext的ApplicationContext類別來加入上述所設的beans.xml,並且取出id為helloBean的物件。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloSpringApp {

    private static Logger logger = LogManager.getLogger(HelloSpringApp.class);

    @SuppressWarnings("resource")
    public static void main(String[] args) {
        
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        
        HelloSpringBean helloSpringBean = (HelloSpringBean) context.getBean("helloBean");
        
        logger.info(helloSpringBean);
    }
  
}

Result Console

大家可以看看最後一行,是不是出現我們剛剛設定的message了呢?

22:56:15.943 [main] INFO  org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@43bd930a: startup date [Tue Sep 05 22:56:15 CST 2017]; root of context hierarchy
22:56:15.973 [main] INFO  org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [beans.xml]
22:56:16.049 [main] INFO  com.spring.example.HelloSpringApp - HelloSpringBean [message=Hello Spring!!]

結語

Spring整個核心圍繞著IOC、DI使用,不論加上哪一種模組,我們都需要設定(Xml or JavaConfig),很多人雖然使用著Spring開發,但卻IOC、DI非常的陌生,更不用說BeanFactory的生命週期了,了解基礎的東西才能讓我們更快速地排除問題,今天這篇文章非常的簡單,我甚至還沒有深入到BeanFactory整個產生Bean的過程,這部分就牽扯到底層的部分。

寫這系列文也是希望自己不要只會開發,也要了解底層的做法,藉此鞭策自己持之以恆的學習,軟體真的是個坑...學起來放(老屁股之路? XD)。

Reference

Spring Tutorial
開源框架: Spring Gossip
极客学院 - IoC 容器

← [LeetCode] Same Tree (Java) [Spring MVC] CH 2. Spring Aspect-Oriented Programming (AOP) →
 
comments powered by Disqus