Spring Bean

Ioc

ioc遵循了依赖导致原则,是一种思想,他将对象的创建由原本的开发者,通过依赖注入的方式,转移给了ioc容器.

组成

BeanFactory

基础的bean创建工厂,主要是提供了getbean(string name),通过名字获取对象.getType(string name)通过名字获取类型,isSingleton(string name)是否是单例等方法.

ApplicationContext

继承了BeanFactory,并提供了一些获取应用名的方法.属于高阶的IOC容器.

BeanDefinition

javabean对象在容器中的表现形式,包含了类的属性,行为,类型,依赖等功能.

实现过程

1.创建beanFactory,扫描resource包下面的xml文件或者@bean等spring容器注解标记的对象,生产一个beanName为元素的arrayList集合.2.实例化bean遍历beanName集合,查找到bean的依赖关系,以递归的方式,一层一层的去使用beanUtil.instance方法初始化bean.3.根据bean的依赖关系,用递归的方式一步步完成bean的依赖注入.

Bean的生命周期

核心步骤图解

1.AbstractBeanFactory.doGetBean方法

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
 
	// 1.根据 beanName 尝试从缓存中获取 Bean,如果缓存中有,则直接return,如果缓存中没有,且Bean不在创建中则返回null
	Object beanInstance = getSingleton(beanName);
	...
	
        if (!typeCheckOnly) {
            //标记名称为 {beanName} 的 Bean 正在创建中
            markBeanAsCreated(beanName);
	}

	// 2.创建 Bean。 虽然方法名称也叫 getSingleton ,但是它传入了一个可以创建 Bean 的匿名函数,它会在内部调用该匿名函数,进行 Bean 的“创建”
	sharedInstance = getSingleton(beanName, () -> { return createBean(beanName, mbd, args); });
    }
}

2.getSingleton(beanName)

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    
    public Object getSingleton(String beanName) {
       return getSingleton(beanName, true);
    }

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
       // 从第一级缓存 singletonObjects 中取
       Object singletonObject = this.singletonObjects.get(beanName);
       if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
          synchronized (this.singletonObjects) {
             // 没取到,从第二级缓存 earlySingletonObjects 中取 
             singletonObject = this.earlySingletonObjects.get(beanName);
             if (singletonObject == null && allowEarlyReference) {
                // 还没取到,从第三级缓存 singletonFactories 中取出该 bean 的工厂对象
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                   // 通过工厂对象生产该 bean 的实例,注意这里拿到的可能是一个 bean 的代理对象
                   singletonObject = singletonFactory.getObject();
                   // 然后添加到第二级缓存 earlySingletonObjects 中
                   this.earlySingletonObjects.put(beanName, singletonObject);
                   // 最后删除掉第三级缓存 singletonFactories 中该 bean 的工厂
                   this.singletonFactories.remove(beanName);
                }
             }
          }
       }
       return singletonObject;
    }
}

3.getSingleton(beanName, ObjectFactory<?>)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // 创建前的处理
    beforeSingletonCreation(beanName);
    //1.创建 bean。singletonFactory 对象,就是上面那段的匿名函数,getObject()方法对应的就是匿名函数的具体实现
    singletonObject = singletonFactory.getObject();
    // 创建后的处理
    afterSingletonCreation(beanName);
    // 2.将 bean 添加到缓存中
    addSingleton(beanName, singletonObject);
    return singletonObject;
}

4.addSingleton()

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
   	  // 将 Bean 添加到第一级缓存中	
      this.singletonObjects.put(beanName, singletonObject);
      // 将 Bean 从第三级缓存中删除
      this.singletonFactories.remove(beanName);
      // 将 Bean 从第二级缓存中删除
      this.earlySingletonObjects.remove(beanName);
      // 标记 {beanName} 对应的 Bean 已创建
      this.registeredSingletons.add(beanName);
   }
}

5.createBean(beanName, mbd, args)

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {
            // 拿到 Bean 的 Definition 对象
            Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
            if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
                mbdToUse = new RootBeanDefinition(mbd);
                mbdToUse.setBeanClass(resolvedClass);
            }
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
	    //如果是aop,则返回代理的对象
	    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            // 调用 doCreateBean() 方法
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	}
}

6.doCreateBean() 方法

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
	    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
        // 1.实例化 Bean,并从返回的 BeanWrapper 包装类中取出 bean 对象。注意此时 bean 还是原始对象
        instanceWrapper = createBeanInstance(beanName, mbd, args);
        final Object bean = instanceWrapper.getWrappedInstance();

        // 是否”提前暴露“原始对象的引用,用于解决循环依赖。对于单例Bean,该变量一般为 true
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            //2.往第三级缓存中添加一个 ObjectFactory 接口的实现类,就是下面这个匿名函数,调用该匿名函数可以获得一个 bean 对象或者 bean 的代理对象,实现 AOP
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // 3.填充属性(依赖注入)
        populateBean(beanName, mbd, instanceWrapper);
        // 4. Bean初始化
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
}

7.addSingletonFactory()

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   synchronized (this.singletonObjects) {
      // 如果 bean 不在第一级缓存中
      if (!this.singletonObjects.containsKey(beanName)) {
         // 将 ObjectFactory 接口的实现类,就是上一节中的匿名函数添加到第三级缓存中
         this.singletonFactories.put(beanName, singletonFactory);
         // 将 bean 从删除第二级缓存中删除
         this.earlySingletonObjects.remove(beanName);
         // 将该 bean 标记为已注册
         this.registeredSingletons.add(beanName);
      }
   }
}

8.populateBean()

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 1.基于 byName 的自动装配
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
       autowireByName(beanName, mbd, bw, newPvs);
    }

    // 2.基于 byType 的自动装配
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
       autowireByType(beanName, mbd, bw, newPvs);
    }
    //默认是AUTOWIRE_NO
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 3.填充属性
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
                return;
            }
        }
    }
}

总结

  1. 实例化,为Bean分配内存空间。

  2. 属性赋值,填充属性和依赖注入。

  3. 初始化:

  • 针对实现了Aware接口的bean,执行各种通知。

  • 执行前置方法。

  • 执行初始化方法。(@PostConstruct)

  • 执行后置方法。

  • 使用Bean,在程序中使用Bean。

  • 销毁Bean,执行Bean的销毁方法。(@PreDestroy)

Bean的循环依赖

出现场景

1.构造方法里面.2.成员变量里面.

出现类型

1.单例2.原型

解决思路

spring对单例的成员变量的循环依赖进行了解决.主要思想是使用三级缓存,提前获取到实例对象的引用,后期赋值.

三级缓存结构

/** Cache of singleton objects: bean name --> bean instance(缓存单例实例化对象的Map集合,value是就绪状态下的bean) 一级缓存*/
//如果是aop,则是代理对象
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64); 

/** Cache of early singleton objects: bean name --> bean instance(早期的单身对象缓存集合,value是只经过实例化,但是没有初始化的bean) 二级缓存*/
//如果是aop,则是代理对象
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
  
/** Cache of singleton factories: bean name --> ObjectFactory(单例的工厂Bean缓存集合) 三级缓存*/
//如果是aop,则会创建代理对象
private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>(16); 

一个含有循环依赖的bean加载主要流程

1.A.getSingleton(beanName)从三级缓存中获取,获取不到。

2.递归引入A的依赖。此时A还没有成员属性。

3.A.getSingleton(name,factory)去创建bean:crateBean().

4.createBean的时候,先实例化bean,然后把获取bean的beanFactory放进三级缓存。

5.填充A的属性,此时会B.getBean()。

6.B执行1-4步骤。

7.填充B的成员变量A。

8.这个时候,A.getSingleton(beanName)从三级缓存中获取,可以获取到A的提前引用。通过从三级缓存中获取的objectFactory,创建A的二级缓存对象,此时A只进行了实例化,没有初始化。

9.B完成属性赋值和初始化。

10.B将初始化好的bean放入一级缓存。

11.A将初始化好的B进行属性赋值,然后初始化。

12.A的bean放入一级缓存。

13.完成。

Bean的线程安全

spring里面的bean是线程安全的吗,比如@contrller,@service,@bean等生成的对象.

答:Spring里面的bean是线程不安全的.

说明:spring默认的注入方式是单例,即所有的对象都会生成一个.必然存在着资源竞争.但是spring又是怎么保证不会出现线程问题呢?

spring里面的bean都是无状态的,既然每个对象都没有状态,就不会存在线程问题了.

每个bean只存在着方法的调用,这部分是在虚拟机栈里面完成,jvm的虚拟机栈是线程安全的.因此不会存在线程问题.

需要注意的是,我们在每个bean里面也要遵循这种原则,bean里面不要写入变量,防止出现线程问题.

注意事项:

  1. 不要在@Controller/@Service等容器中变量,默认的单例是线程不安全的.

  2. 不要在@Controller/@Service等容器中定义静态变量,不论是单例(singleton)还是多实例(prototype)他都是线程不安全的.

  3. 如果要使用共享变量的话,使用threadLocal.

spring 只使用二级缓存可以解决循环依赖吗?

如果只使用二级缓存也是可以解决的,使用三级缓存的目的1是为了延迟实例化,2是为了更好的符合aop的设计原则:实例化,属性赋值,初始话,生成aop对象。如果只使用二级缓存,则会破坏这个原则。

Last updated

Was this helpful?