Spring IOC入門:從Hello world到Spring

從Hello world開始

先上一段代碼:java

public class HelloWorldTest {

    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

這是Java裏面最簡單的一段代碼了,作的事情很是簡單:控制檯打印出「Hello world!」字符串。很明顯,這段代碼很很差拓展,假如咱們想打印別的內容呢?ide

第一步改動

OK,接下來作一點簡單的改動:函數

public class HelloWorldTest {

    public static void main(String[] args) {
        if (args.length > 0) {
            System.out.println(args[0]);
        } else {
            System.out.println("Hello world!");
        }
    }
}

這樣當咱們運行帶參數時,控制檯會輸出咱們的第一個參數。這樣咱們就取得了第一個小小的進步:咱們能夠不修改代碼就控制了不一樣的輸出。但還有問題,這個類既控制了參數的輸入,又控制了參數的輸出。換句話說就是:消息的輸入和輸出是耦合在一塊兒的。this

進一步解耦

讓咱們更進一步。首先咱們添加一個獲取消息的類:spa

public class MessageConsumer {

    public String sayHello(String message) {
        if (Objects.isNull(message) || message.length() < 1) {
            return "Hello world!";
        }
        return message;
    }
}

這樣當輸入的參數不爲null或者空字符串時,輸出參數,不然輸出Hello world!。調用方只須要在調用的時候傳入不一樣的參數,就達到了輸出不一樣內容的目的。OK,如今已經解耦了消息的輸出方,但生產方還在main方法裏。接下來解耦消息的生產方。添加一個新的類來生產消息:code

public class MessageRenderer {
    private MessageConsumer messageConsumer;

    public void render(){
        if (Objects.isNull(messageConsumer)){
            System.out.println("Hello world!");
        }else {
            System.out.println(messageConsumer.sayHello("MessageRenderer"));
        }
    }

    public MessageConsumer getMessageConsumer() {
        return messageConsumer;
    }

    public void setMessageConsumer(MessageConsumer messageConsumer) {
        this.messageConsumer = messageConsumer;
    }
}

這樣主函數只須要new出MessageRenderer和MessageConsumer對象便可,對於消息怎麼生產和消費則不須要關心。但這樣的問題是MessageRender和MessageConsumer耦合在一塊兒。對象

面向接口

咱們更進一步對兩個類進行抽象:blog

public interface MessageConsumer {

    String sayHello(String message);
}
public interface MessageRenderer {

    void render();

    MessageConsumer getMessageConsumer();

    void setMessageConsumer(MessageConsumer messageConsumer);
}

新建實現類:接口

public class HelloWorldMessageConsumer implements MessageConsumer {

    @Override
    public String sayHello(String message) {
        return message;
    }
}
public class HelloWorldMessageRenderer implements MessageRenderer {

    private MessageConsumer messageConsumer;

    @Override
    public void render() {
        if (Objects.isNull(messageConsumer)) {
            System.out.println("Hello world!");
        } else {
            System.out.println(messageConsumer.sayHello("HelloWorldMessageRenderer"));
        }
    }

    @Override
    public MessageConsumer getMessageConsumer() {
        return messageConsumer;
    }

    @Override
    public void setMessageConsumer(MessageConsumer messageConsumer) {
        this.messageConsumer = messageConsumer;
    }
}

程序入口:圖片

public class HelloWorldTest {

    public static void main(String[] args) {
        MessageRenderer renderer = new HelloWorldMessageRenderer();
        MessageConsumer consumer = new HelloWorldMessageConsumer();
        renderer.setMessageConsumer(consumer);
        renderer.render();
    }
}

至此,消息的生產和消費解耦開來,生產方只依賴消費方的抽象而不是具體實現,主程序只負責new出須要的生產方和消費方便可。三者的關係如如:

圖片描述

運行程序咱們能夠獲得咱們想要的輸出內容,但還有一點小問題:咱們如今要的是HelloWorldMessageConsumer,假如咱們須要別的MessageConsumer呢?那就須要改主程序代碼了。

簡易版IOC

下面咱們添加一個類來生產MessageConsumer和MessageRenderer:

public class MessageSupportFactory {

    private static MessageSupportFactory instance;
    private Properties properties;
    private MessageRenderer messageRenderer;
    private MessageConsumer messageConsumer;

    static {
        instance = new MessageSupportFactory();
    }

    public static MessageSupportFactory getInstance() {
        return instance;
    }

    private MessageSupportFactory() {
        properties = new Properties();
        try {
            properties.load(this.getClass().getResourceAsStream("/msf.properties"));
            String rendererClass = properties.getProperty("renderer.class");
            String consumerClass = properties.getProperty("consumer.class");

            messageRenderer = (MessageRenderer) Class.forName(rendererClass).newInstance();
            messageConsumer = (MessageConsumer) Class.forName(consumerClass).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public MessageRenderer getMessageRenderer() {
        return messageRenderer;
    }

    public MessageConsumer getMessageConsumer() {
        return messageConsumer;
    }
}

msg.properties代碼以下:

renderer.class=org.chunrun.learn.sp.message.HelloWorldMessageRenderer
consumer.class=org.chunrun.learn.sp.message.HelloWorldMessageConsumer

主程序代碼以下:

public class HelloWorldTest {

    public static void main(String[] args) {
        MessageConsumer consumer = MessageSupportFactory.getInstance().getMessageConsumer();
        MessageRenderer renderer = MessageSupportFactory.getInstance().getMessageRenderer();
        renderer.setMessageConsumer(consumer);
        renderer.render();
    }
}

這樣,當咱們須要不一樣的MessageRenderer或MessageConsumer時,只須要在配置文件裏指定不一樣的對象便可。實際上,到這裏已經完成了一個簡易版的IOC實現。

使用Spring重構

這部分只須要添加配置便可,略。

相關文章
相關標籤/搜索