实现控制反转(Ioc)的方式有很多种,依赖注入(DI)是实现控制反转的一种方法.
分别在其中定义了相应的接口.
在UserDao接口中定义了一个getUserName方法
package dao;
/**
* @Author Yiang37
* @Date 2020/4/30 20:16
* Description:
*/
public interface UserDao {
void getUserName();
}
它有两个实现类UserDaoImplByMysql与UserDaoImplByOracle
UserDaoImplByMysql代码如下
package dao.impl;
import dao.UserDao;
/**
* @Class: UserDaoImplByMysql
* @Author: Yiang37
* @Date: 2020/4/30 20:19
* @Description:
*/
public class UserDaoImplByMysql implements UserDao {
public void getUserName() {
System.out.println("我是Mysql的getUserName");
}
}
UserDaoImplByOracle代码如下
package dao.impl;
import dao.UserDao;
/**
* @Class: UserDaoImpl
* @Author: Yiang37
* @Date: 2020/4/30 20:17
* @Description:
*/
public class UserDaoImplByOracle implements UserDao {
public void getUserName() {
System.out.println("我是Oracle的getUserName");
}
}
在UserService接口中定义了一个outUserName()方法
package service;
/**
* @Class: UserService
* @Author: Yiang37
* @Date: 2020/4/30 20:21
* @Description:
*/
public interface UserService {
void outUserName();
}
它有一个实现类UserServiceImpl
UserServiceImpl代码如下
package service.impl;
import dao.UserDao;
import dao.impl.UserDaoImplByMysql;
import service.UserService;
/**
* @Class: UserService
* @Author: Yiang37
* @Date: 2020/4/30 20:21
* @Description:
*/
public class UserServiceImpl implements UserService {
UserDao userDao = new UserDaoImplByMysql();
public void outUserName() {
userDao.getUserName();
}
}
import service.UserService;
import service.impl.UserServiceImpl;
/**
* @Class: Test1
* @Author: Yiang37
* @Date: 2020/4/30 20:23
* @Description:
*/
public class Test1 {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
userService.outUserName();
}
}
可以看到程序输出
我是Mysql的getUserName
在上面的内容中我们看到userService.outUserName()在执行后输出了
我是Mysql的getUserName
为什么会是这个结果?这还得回到UserServiceImpl的代码中
1. public class UserServiceImpl implements UserService {
2.
3. UserDao userDao = new UserDaoImplByMysql();
4.
5. public void outUserName() {
6. userDao.getUserName();
7. }
8. }
我们看到在代码的第6行调用了userDao.getUserName();
而这个userDao是谁呢?
在代码的第3行指定了
UserDao userDao = new UserDaoImplByMysql();
现在问题来了,我们想修改为UserDaoImplByOracle()来实现?
可以更改上面userDao的具体实现类
UserDao userDao = new UserDaoImplByOracle();
程序输出了我们想要的结果
我是Oracle的getUserName
通过上面的方式,虽然能达到结果,但是我们得修改掉原来的代码
在调用userDao时,我们就得明确的指明它的实现类.
我们是否可以每次为userService动态的指定其中的userDao呢?
修改我们的代码,变成下面这样.
public class UserServiceImpl implements UserService {
//成员变量UserDao
private UserDao userDao;
//UserDao属性的set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void outUserName() {
userDao.getUserName();
}
}
现在我们再修改测试类
public class Test1 {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
((UserServiceImpl)userService).setUserDao(new UserDaoImplByMysql());
userService.outUserName();
}
}
注:
UserService userService = new UserServiceImpl();
左侧是UserService类型,是找不到setUserDao()方法的.
所以在setUserDao()方法之前进行了类型转换.
( (UserServiceImpl) userService).xx
当创建时指明类型为UserServiceImpl时才有这个方法
"多态相关知识"
现在我们通过set方法为其注入了UserDaoImplByMysql对象,再次运行.
我是Mysql的getUserName
为其set进不同的值,例如.
((UserServiceImpl)userService).setUserDao(new UserDaoImplByOracle());
同样能成功输出想要的内容
我是Oracle的getUserName
一开始是程序主动设置userDao对象,现在变成了程序被动的接收userDao对象.
我们可以看到,通过后者,无需更改UserServiceImpl中的任何内容.
只是在使用通过set注入,即可实现想要的效果.
当写了新的userDao时,例如.
public class UserDaoImplBySqlServer implements UserDao {
public void getUserName() {
System.out.println("我是SqlServer的getUserName");
}
}
然后在使用时set进不同的内容
((UserServiceImpl)userService).setUserDao(new UserDaoImplBySqlServer());
输出值即可改变
我是SqlServer的getUserName
通过上面的方式,写代码时不用再去管理对象的创建了.
例如UserServiceImpl中的userDao对象我们不用显示的指明,而是可以从外部动态的(被动的)接收.
控制反转,现在是不是反转了,这就是Ioc的原型.
原文:https://www.cnblogs.com/yang37/p/12811265.html