IoC in Spring

  写两个关于Spring中使用IoC的小例子,一个是半动态创建Bean,另一个是全动态创建Bean,它们适合不同的应用场景。

  一、半动态:在一个实际项目中遇到过这样的问题,项目组开发的某个系统具备在LED屏上显示信息的功能。不同客户那里的LED屏各不相同,主要区别是驱动卡和显示格式。如果每次换LED屏时都是靠程序员去替换不同实现的代码,成本可想而知。那么,在不修改既有代码(甚至是不用编译既有工程)的情况下,怎样才能让系统的这个功能适应变化呢?

  首先抽象出一个接口,代表向LED屏打印的功能。

package com.mmh.printer;

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

  然后根据不同品牌的LED屏,编写具体的打印功能。

package com.mmh.printer;

public class Brand1LEDPrinter implements LEDPrinter {

    @Override
    public void print(String content) {
        // 模拟不同品牌的LED显示屏操作
        System.out.println("这是品牌1的LED显示内容: " + content);
    }
}

  紧接着编写一个辅助类,客户端程序通过它实现LED屏的打印功能。

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);
    }
}

  最后实现一个客户端调用的演示程序。

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屏,那么程序员只需要针对这种屏编写具体操作即可。

package com.mmh.printer;

public class Brand2LEDPrinter implements LEDPrinter {

    @Override
    public void print(String content) {
        // 模拟不同品牌的LED显示屏操作
        System.out.println("这是品牌2的LED显示内容: " + content);
    }
}

这个具体实现类完全可以封装到一个单独的jar中,那么以前的既有代码对于现在的开发人员可以完全透明。

  应对变化的功能是靠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="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屏的具体操作。

  二、全动态:在实际项目中还遇到过这样的问题,不同类型用户的登录实现方式是不同的,并且在系统的使用过程中用户的类型会不断增加。那么,在不修改既有代码(甚至是不用编译既有工程)的情况下,怎样才能让系统的这个功能适应变化呢?

  首先抽象一个接口,代表用户登录功能。

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>
原文地址:https://www.cnblogs.com/gofblogs/p/3216293.html