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重构

这部分只须要添加配置便可,略。