控制反转 IOC 理论推导
按照我们传统的开发,我们会先去 dao 层创建一个接口,在接口中定义方法。
public interface UserDao {
void getUser();
}
然后再去实现类中实现这个方法的作用。
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("默认获取用户的数据");
}
}
然后再去 service 层写一个接口,在接口中定义方法。
public interface UserService {
void getUser();
}
再然后写实现类,实现里面的方法。
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
然后我们使用这业务类
public class MyTest {
public static void main(String[] args) {
// 用户实际调用的是业务层,dao 层他们不需要接触
UserService userService = new UserServiceImpl();
userService.getUser();
}
}
最后会输出
默认获取用户的数据
但是现在在 dao 层新增加了一个实现,例如 UserDaomySql
public class UserDaoMysql implements UserDao {
@Override
public void getUser() {
System.out.println("从 MySQL 中获取数据");
}
}
如果我们想要从 UserDaoMysql 这个类中调用 getUser() 这个方法,就需要在 UserServiceImpl 这个类中修改代码,将创建的 UserDaoImpl 改为 UserMysqlImpl 这个对象。然后才能得到我们想要的效果。
从 MySQL 中获取数据
如果用户就像产品经理一样,今天要你想要在 UserDaoImpl 这个对象中获取数据,明天就想要从 UserDaoMysql 这个对象中获取数据呢?
我们面对这样的问题,是不是还要每次去修改代码,如果我们在很多地方创建了这个对象,岂不是要到处修改,或者有更多的实现类,产品经理又突然叫我们用另一个对象,这样我们就会被折磨死。是吧!
我们都知道猴子的脸说变就变,产品经理何尝不是?
那么我们可以不可以这样做,我们就吧选择权交给产品经理,我们不按照我们的意愿去创建这个对象,我们将这个问题抛给产品经理,诶,我不建,我让他去选,他喜欢用哪个,那就创建哪个。
我们来看看我们在 UserServiceImpl 中创建对象的那条语句
private UserDao userDao = new UserDaoImpl();
我想聪明的你,看到这条语句你就很快能明白,这个不就是定义一个对象变量,然后创建一个对象,将其赋值给它。
那么我们可不可以想个办法,让他动态的将这个对象注入到这个变量里面呢?
聪明的你仔细想想,想想我们创建实体类的时候。
嘿嘿!!!
是不是想到了什么。
我们创建实体类的时候,是不是一开始我们没有为那个变量赋值,是后面才用 Set 赋值的吧。
所以是不是想到该怎么做了,嘿嘿嘿
没错,我们就是写个 Setter
private UserDao userDao;
/**
* 利用 Set 进行动态实现值的注入
* @param userDao dao 层的对象
*/
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
我写的和你想的一样吗?我想是的吧。
然后我们使用它
public class MyTest {
public static void main(String[] args) {
// 用户实际调用的是业务层,dao 层他们不需要接触
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoMysql());
userService.getUser();
}
}
这样我们是不是就可以随便产品经理怎么想了,他爱用啥用啥,让他自己选一个创建就好了。
这样我们是不是就实现了反转,诶,我不创建对象,让你来选,你喜欢哪一个,就用哪一个。