概述
- Spring 单例缓存实现原理:synchronized+双重判断。
- Spring 真正createBean的2种方式:反射 (未重写父类方法时)、CGLIB(重写了)
单例模式抽象版
java实现单例模式有多种方式:饿汉式、懒汉式等等,Spring 传统的BeanFactory采用的是懒汉式。通过双重校验+锁的方式实现单例模式
实现的代码在AbstractBeanFactory.doGetBean()来实现的,简化后的代码如下
public Object getSingotonByBeanName(String beanName){
Object bean=getSingleton(String beanName, boolean allowEarlyReference) ;
if(bean==null){
synchronized (this.singletonObjects) {
//双重校验
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = singletonFactory.createBean();
addSingleton(beanName, singletonObject);
}
return singletonObject;
}
}
}
单例模式源码分析
核心方法通过AbstractBeanFactory实现的
- 最开始会做一个Eagerly check,如果是单例且已经缓存,后面就不用管了,直接返回单例
- 做完一些校验之后,再加锁(this.singletonObjects 这个对象),Double Check之后,再创建Bean,创建完之后缓存在singletonObjects里面
- 创建Bean的时候加了锁,addSingleton时候也重入了该锁
AbstractBeanFactory.class
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) {
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
...
//各种检查之后,最后再来一次针对单例模式的getSingleton Check
//通过加锁的方式,保证只有一个线程成功的创建bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() {return createBean(beanName, mbd, args);}});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
DefaultSingletonBeanRegistry.class
//第一次 Eagerly check
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 != NULL_OBJECT ? singletonObject : null);
}
// 保证线程安全的 加锁 -->doubleCheck --> create And buffer
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
newSingleton = true;
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
真正创建Bean的两种方式
org.springframework.beans.factory.support.SimpleInstantiationStrategy.class
- 如果未重写父类方法的类,则通过指定的构造器+构造函数的参数值,反射实例化对象, 默认是无参的构造函数反射,也可以在xml指定实例化的构造函数和参数值
- 如果重写父类的方法,则只能通过CGLIB的方式创建Bean
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
- 反射的使用
org.springframework.beans.BeanUtils.class
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}