前言:
之前写过一篇文章:
[Spring]什么是IOC-好莱坞原则
那么把这个再看一下当时写的内容,然后整理一下更多关于IOC的面试内容。
1. Ioc的面试引导
Inversion of Control:主要是控制反转,其中包括依赖注入和依赖查找。
什么是好莱坞原则:你不要老是轮询的询问我,我要去通知你。
我感觉就是你作为客户端,或者说是spring的上层,不需要关心spring 底层是怎么实现的这个东西。
我们只需要去拿就可以了,而不用一直去问spring 创建了么?
这个好莱坞原则是针对me来说的,也就是,我作为上层,我只需要去给容器打电话,而容器你不要老是来告诉我创建好了。
我需要我就去找你拿了
2. Open Closed Principle, OCP原则是什么?
一个软件实体如类,模块和函数应该对扩展开放,对修改关闭。
这个也是设计的一种理念。可以引出自己的设计理念~
比如设计模式如我代码常用策略模式和工厂模式
3.Ioc的通俗解释
这是一种主动提供服务的思想。
Ioc让spring负责创建对象的生命周期和对象质检的关系,我们传统的话在代码中总是创建bean什么的实例什么的,会给修改代码什么都带来不便。
在传统的程序开发中,完成一个业务逻辑至少需要两个或两个以上的对象协助完成。通常一个对象要使用另外一个对象,都是直接在对象内部通过new进行创建对象,由程序主动去创建以来对象。 但这就代表着当前的模块和它所依赖的对象紧紧耦合了。
(那我们在代码中就不要耦合创建对象的部分了,让spring管理我们就关注业务的本身。这样不让他的模块与依赖紧紧耦合)
传统程序开发: 主动创建对象—>组装对象
但是,IOC容器:生产线—创建和组装对象,客户端直接获取
所以感觉spring就是一个大的工厂~
4.DI
Spring的Ioc容器主要使用DI方式实现的,不需要主动查找,在系统运行过程中,动态的向某个对象提供它所需要的其他对象。
可以说@Autowired就是注入的一种吧~我感觉
所以需要用啥,就注入啥进入到这个类,我们不需要关心什么时候创建,怎么创建的。
依赖注入主要是通过反射机制来实现的。同时IOC提供了三种依赖注入的方式,分别是构造方法注入、setter方法注入和接口方法注入。
比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。
4.1 那么如何通过setter注入?
极其复古的方式,但是也很能说明是通过setter注入
现在不会再通过这种xml来配置spring的内容了。
public class UserDao {
public String userLogin () {
return "用户登录成功";
}
}
public class UserService {
private UserDao userDao ;
public void userLogin () {
String res = userDao.userLogin();
System.out.println(res);
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
<?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="userDao" class="com.dk.test.dao.UserDao"></bean>
<!-- 第一种 setter注入 -->
<bean id= "userService" class = "com.dk.test.dao.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
参考链接:https://www.cnblogs.com/shsxt/p/8335883.html
但是链接中有写的不太对的地方
5.@Autowired和@Resource
面试官提到spring中的IOC就很容易问道@Autowired和@Resource的区别。
其实这个问题,@Resource我第一个反应就是,一般对mybatis的Dao接口上面,使用@Resource字段进行实现。
@Autowired和@Resource都是用来专配Bean的,这两个注解可以在字段使用,也可以在setter方法使用。
//基于@Autowired注解注入
public class UserServiceImpl{
@Autowired
private UserDao userDao;
private RoleDao roleDao;
.....
@AutoWired
public void setRoleDao(RoleDao roleDao){
this.roleDao = roleDao
}
}
//基于@Resource注解注入
public class UserServiceImpl{
@Resource
private UserDao userDao;
private RoleDao roleDao;
.....
@Resource
public void setRoleDao(RoleDao roleDao){
this.roleDao = roleDao
}
}
5.1 @Autowired和@Resource两个的区别之一
- @AutoWired是spring中注解,主要是使用类型来进行注入
- @Resource是JDK1.6支持的注解,默认使用名称进行注入,如果没有匹配到name属性指定,则使用类型注入。
5.2 什么叫做类型注入什么叫做名称注入呢?
- byName:通过参数名自动注入,如果一个bean的name与另一个bean的property相同,就自动注入
- byType:通过参数的数据类型自动注入,如果一个bean的数据类型与另外一个bean的property属性的数据类型兼容,就自动注入
//property大概就是
@Resource
private UserDao userDao; //这个过程发现这个东西跟另一个bean的name相同 那么就注入
//通过数据类型的话,可能是看class文件的?
@Resource 可以减少代码与Spring的耦合。
5.3 代码举例
public interface Human {
public void speak();
}
@Service
public class ManImpl implements Human {
public void speak() {
System.out.println(" man speaking!");
}
}
@Service
public class WomanImpl implements Human {
public void speak() {
System.out.println(" woman speaking!");
}
@Service
public class SequenceServiceImpl implements SequenceService {
@Resource
private SequenceMapper sequenceMapper;
public void generateId(Map<String, String> map) {
sequenceMapper.generateId(map);
}
//起服务此处会报错,因为不知道要注入那个类
//@Resource
//private Human human;
//注意是manImpl不是ManImpl,因为使用@Service,容器为我们创建bean时默认类名首字母小写
//这个类似于获取spring容器中get bean方法
@Resource(name = "manImpl")
private Human human;
}
//如果用Autowired
@Autowired
@Qualifier("manImpl")
private Human human2;
}
当然代码中可能更多也会直接用具体的实现类来注入这个东西,这样不香吗?
@Autowired
private ManImpl human;
5.3 这部分代码参考自:https://www.cnblogs.com/qq3245792286/p/11151193.html
那么面试IOC的准备到此完结~