IoC in Spring

  寫兩個關於Spring中使用IoC的小例子,一個是半動態建立Bean,另外一個是全動態建立Bean,它們適合不一樣的應用場景。程序員

  1、半動態:在一個實際項目中遇到過這樣的問題,項目組開發的某個系統具有在LED屏上顯示信息的功能。不一樣客戶那裏的LED屏各不相同,主要區別是驅動卡和顯示格式。若是每次換LED屏時都是靠程序員去替換不一樣實現的代碼,成本可想而知。那麼,在不修改既有代碼(甚至是不用編譯既有工程)的狀況下,怎樣才能讓系統的這個功能適應變化呢?web

  首先抽象出一個接口,表明向LED屏打印的功能。spring

package com.mmh.printer;

public interface LEDPrinter {
    
    public void print(String content);
}

  而後根據不一樣品牌的LED屏,編寫具體的打印功能。app

package com.mmh.printer;

public class Brand1LEDPrinter implements LEDPrinter {

    @Override
    public void print(String content) {
        // 模擬不一樣品牌的LED顯示屏操做
        System.out.println("這是品牌1的LED顯示內容: " + content);
    }
}

  緊接着編寫一個輔助類,客戶端程序經過它實現LED屏的打印功能。ide

package com.mmh.printer;

public class LEDPrintHelper {
    
    private LEDPrinter printer;
    
    public void setPrinter(LEDPrinter printer) {
        this.printer = printer;
    }
    
    public void print(String content) {
        printer.print(content);
    }
}

  最後實現一個客戶端調用的演示程序。this

package com.mmh.main;

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

import com.mmh.printer.LEDPrintHelper;

public class Application {
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "appContext.xml");
        
        LEDPrintHelper ledPrintHelper = (LEDPrintHelper) context.getBean("LEDPrintHelper");
        ledPrintHelper.print("業務層產生的數據");
    }
}

  在LED屏更換時,以上的代碼,無論是調用方的仍是被調用方的,都不須要作任何的修改。假設如今客戶使用的是Brand2品牌LED屏,那麼程序員只須要針對這種屏編寫具體操做便可。spa

package com.mmh.printer;

public class Brand2LEDPrinter implements LEDPrinter {

    @Override
    public void print(String content) {
        // 模擬不一樣品牌的LED顯示屏操做
        System.out.println("這是品牌2的LED顯示內容: " + content);
    }
}

這個具體實現類徹底能夠封裝到一個單獨的jar中,那麼之前的既有代碼對於如今的開發人員能夠徹底透明。code

  應對變化的功能是靠Spring的IoC來實現的。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="LEDPrintHelper" class="com.mmh.printer.LEDPrintHelper">
        <property name="printer" ref="Brand1LEDPrinter" />
    </bean>

    <bean id="Brand1LEDPrinter" class="com.mmh.printer.Brand1LEDPrinter" />
    
    <bean id="Brand2LEDPrinter" class="com.mmh.printer.Brand2LEDPrinter" />

</beans>

該配置文件定義了三個Bean,LEDPrintHelper是調用程序的接口,Brand1LEDPrinter和Brand2LEDPrinter分別表明了兩種屏的具體操做。經過屬性注入的方式,開發人員手動修改(這就是半動態的意思)LEDPrintHelper的printer屬性值,從而更改LED屏的具體操做。blog

  2、全動態:在實際項目中還遇到過這樣的問題,不一樣類型用戶的登陸實現方式是不一樣的,而且在系統的使用過程當中用戶的類型會不斷增長。那麼,在不修改既有代碼(甚至是不用編譯既有工程)的狀況下,怎樣才能讓系統的這個功能適應變化呢?

  首先抽象一個接口,表明用戶登陸功能。

package com.mmh.login;

public interface UserLogin {
    public boolean login(String username, String password);
}

  而後實現不一樣類型用戶的登陸過程。

package com.mmh.login;

public class UserALogin implements UserLogin {

    @Override
    public boolean login(String username, String password) {
        System.out.println("根據UserA的業務邏輯處理登陸過程");
        
        return true;
    }
}
package com.mmh.login;

public class UserBLogin implements UserLogin {
    
    @Override
    public boolean login(String username, String password) {
        System.out.println("根據UserB的業務邏輯處理登陸過程");
        
        return true;
    }
}

  緊接着開放給客戶調用端一個統一的接口。這個接口在實際系統中常常會被實現爲一個web service。

package com.mmh.login;

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

public class UserLoginService {

    private ApplicationContext context = new ClassPathXmlApplicationContext(
            "appContext.xml");

    public boolean login(String username, String password, String logintype) {
        UserLogin userLogin = (UserLogin) context.getBean(logintype);

        return userLogin.login(username, password);
    }
}

  最後仍是編寫一個客戶調用的演示。

package com.mmh.main;

import com.mmh.login.UserLoginService;

public class Application {

    public static void main(String[] args) {
        UserLoginService service = new UserLoginService();
        
        service.login("userA", "123456", "UserALogin");
        
        service.login("userB", "123456", "UserBLogin");
    }
}

  從上面的代碼能夠看到,不一樣的用戶能夠調用相同的接口進行不一樣的登陸操做,被調用程序根據用戶輸入的參數自動匹配登陸過程(這就是全動態的意思)。而且當系統增長用戶類型時,既有代碼不須要修改。應對變化的功能還是靠Spring的IoC來實現的。

<?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="UserALogin" class="com.mmh.login.UserALogin" />
    
    <bean id="UserBLogin" class="com.mmh.login.UserBLogin" />

</beans>
相關文章
相關標籤/搜索