IOC理论推导

HeJin大约 3 分钟Spring全家桶Spring入门

原来的步骤

UserDao.java接口

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/2 19:01
 */
public interface UserDao {
    /**
     * 获取用户
     */
    void getUser();
}

UserDaoImpl.java实现类

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/2 19:01
 */
public class UserDaoImpl implements UserDao {
    public void getUser() {
        System.out.println("默认获取用户的数据");
    }
}

UserService.java业务接口

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/2 19:02
 */
public interface UserService {
    /**
     * 获取用户
     */
    void getUser();
}

UserServiceImpl.java业务实现类

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/2 19:03
 */
public class UserServiceImpl implements UserService {

    /**
     * 组合引用调用dao层
     */
    UserDao userDao = new UserDaoMySqlImpl();

    public void getUser() {
        userDao.getUser();
    }

}

业务调用

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/2 19:05
 */
public class MyTest {

    public static void main(String[] args) {
        /**
         * 用户实际调用的业务
         * dao层他们不需要接触
         */
        UserService service = new UserServiceImpl();
        service.getUser();
    }
}

测试结果

默认获取用户的数据

Process finished with exit code 0

需求有变动

需要使用MySQL数据库实现。则需要一个UserDao接口的MySQL实现类。并且在UserServiceImpl实现类中修改调用的dao层代码。

UserDaoMySqlImpl.java

/**
 * @Description UserDao接口MySQL实现
 * @Author Administrator
 * @Date 2020/12/2 19:08
 */
public class UserDaoMySqlImpl implements UserDao {

    public void getUser() {
        System.out.println("MySQL获取数据");
    }
}

UserServiceImpl.java实现类中修改

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/2 19:03
 */
public class UserServiceImpl implements UserService {

    /**
     * 组合引用调用dao层
     */
//    UserDao userDao = new UserDaoImpl(); // 默认实现
    UserDao userDao = new UserDaoMySqlImpl();
    public void getUser() {
        userDao.getUser();
    }
}

测试结果

MySQL获取数据

Process finished with exit code 0

缺陷

程序适应不了需求。每次需求变动都需要新增dao层实现类,并且修改service层实现类的调用代码。代码修改太多。当需求变得很频繁时,工作量太大。

改进

在之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求取修改原代码!如果程序代码量十分大,修改一次的代价十分昂贵!

我们在service层的实现类中使用一个set接口实现:

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/2 19:03
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    /**
     * 利用set方法动态实现值的注入
     * @param userDao
     */
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void getUser() {
        userDao.getUser();
    }
}

业务调用:

public static void main(String[] args) {
    /**
     * 用户实际调用的业务
     * dao层他们不需要接触
     */
    UserService userService = new UserServiceImpl();
    UserDao userDao = new UserDaoMySqlImpl();
    ((UserServiceImpl) userService).setUserDao(userDao);
    userService.getUser();

}

结果

MySQL获取数据

Process finished with exit code 0

把对UserDao的实现选择权交给了用户。service层的代码不用再修改。只需要扩展UserDao接口实现类,以及再业务调用的实现选择调用哪一种实现即可。service层代码不用在修改。

分析

  • 之前,是程序主动创建对象!控制权在程序猿手上!
  • 使用了set注入后,程序不再具有主动性。而是变成了被动的接收对象

这种思想,从本质上解决了问题。我们能程序猿不用再去管理对象的创建了。系统的耦合性大大降低。可以更加地专注业务的实现。