什么是ioc?

IOC(inversion of control),就是控制反转的意思。何为控制反转?根据字⾯意思理解,就是对于某个东⻄A,原来的控制权在使⽤⽅B,B想⽤就能⽤,不想⽤就不⽤。现在把控制权交还给了A,只有A给了才能⽤,这样就是控制反转了。

1
2
3
4
5
6
7
8
9
class A {}
class B {
// B需要将A的实例new出来,也就是我们说的控制
private A a = new A();
public void use() {
System.out.print(a);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
// A自行控制将自己作为bean注入ioc容器中
@conponent
class A {}

class B {
// B根据需要从ioc容器中注入A, B 能注入A 的前提是A将自己暴露出去了
@Autowired
private A a;
public void use() {
System.out.print(a);
}

}

两个例子中,例子一中,类B中想使用A new一个对象即可,而例子二中,类B中想使用A需要A将自己作为bean提前注入IOC容器中,以此实现控制反转。

ioc的优点
  1. 使用者并不关心引入bean的实现,无需关注该bean的构造器参数等。
  2. 多个使用者不需要重复创建bean。
  3. 使用者无需感知bean的修改。
spring 的 ioc

spring的ioc,是ioc思想的一种实现方式。在容器启动的时候,会依据每个bean的定义将bean注入到spring容器中。如果bean之间有依赖关系,则会将依赖的bean先注入。如果依赖的bean已注入,泽直接从容器中获取使用。

什么是AOP?

AOP(Aspect-Oriented Programming),即⾯向切⾯编程,即把公共的逻辑抽出来,
让开发者可以更专注于业务逻辑开发。

spring 如何处理循环引用问题

在Spring框架中,循环依赖是指两个或多个bean之间相互依赖,形成了⼀个循环引⽤的情况。如
果不加以处理,这种情况会导致应⽤程序启动失败。

1
2
3
4
5
6
7
8
9
10
@Service
public class ServiceA{
@Autowired
private ServiceB serviceB;
}
@Service
public class ServiceB{
@Autowired
private ServiceA serviceA;
}

什么是三级缓存?

在Spring的BeanFactory体系中,BeanFactorySpring IoC容器的基础接⼝,DefaultSingletonBeanRegistry类实现了
BeanFactory接⼝,并且维护了三级缓存:

1
2
3
4
5
6
7
8
9
10
11
/** Cache of singleton objects: bean name to bean instance. */
// 缓存从bean name 到 单例bean实例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
// 缓存 bean name到 bean 单例工厂
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
// 缓存 bean 名称到 ealy单例实例
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

其中,

  • singletonObjects是一级缓存,缓存完整创建好的单例bean对象;在创建bean对象时,会尝试从singletonObjects中获取该bean实例,如果能获取到,则直接返回该实例;否则继续创建该实例。
  • earlySingletonObjects是二级缓存,存储的是尚未完全创建好的单例bean对象;在创建单例bean时,如果发现该bean存在循环依赖,则会先创建bean的 半成品 对象,并将它存储到earlySingletonObjects中。当循环依赖的bean创建完成后,spring会将完整的bean实例存储到singletonObjects中,并将earlySingletonObjects中存储的代理对象替换为完整的bean实例对象。以防止在单例bean的创建过程中出现循环依赖问题。
  • singletonFactories是三级缓存,存储的是单例bean的创建工厂。当一个单例bean被创建时,spring会先将该bean的创建工厂存储到singletonFactories中,在执行创建工厂的getobject()方法,生成该bean的实例对象,在该bean被其他bean引用时,spring会从singletonFactories中获取该bean的创建工厂,创建出该bean的实例对象,并将该bean的实例对象存储到singletonFactories中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}

/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

spring解决循环引用的方式就是引入了三级缓存。
但是要注意的是,spring解决三级缓存是有条件的

  1. 相互依赖的bean必须是单例的
  2. 依赖注入的方式不能都是构造函数注入的

引用

1.