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>
相关文章
相关标签/搜索