zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Spring获取单例getSingleton(1)

Spring 获取 单例
2023-09-14 09:00:26 时间

spring获取单例首先是从缓存去找,如果找不到就要从头开始bean的加载过程,spring中主要通过getSingleton的重载方法实现单例bean的加载过程

要创建一个bean的单例,首先了解下单例是什么样子的,

 public static synchronized Singleton getInstance() { 

 if (single == null) { 

 single = new Singleton(); 

 return single; 

 } 

spring创建单例bean主要查看 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry类的getSingleton(String beanName, ObjectFactory

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) {

 if (this.singletonsCurrentlyInDestruction) {

 throw new BeanCreationNotAllowedException(beanName,

 "Singleton bean creation not allowed while the singletons of this factory are in destruction " +

 "(Do not request a bean from a BeanFactory in a destroy method implementation!)");

 if (logger.isDebugEnabled()) {

 logger.debug("Creating shared instance of singleton bean " + beanName + "");

 //把当前正在创建的bean记录在缓存中,对循环依赖进行检测

 beforeSingletonCreation(beanName);

 boolean newSingleton = false;

 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);

 if (recordSuppressedExceptions) {

 this.suppressedExceptions = new LinkedHashSet Exception 

 try {

 //使用回调方法 创建单例bean

 singletonObject = singletonFactory.getObject();

 newSingleton = true;

 catch (IllegalStateException ex) {

 singletonObject = this.singletonObjects.get(beanName);

 if (singletonObject == null) {

 throw ex;

 catch (BeanCreationException ex) {

 if (recordSuppressedExceptions) {

 for (Exception suppressedException : this.suppressedExceptions) {

 ex.addRelatedCause(suppressedException);

 throw ex;

 finally {

 if (recordSuppressedExceptions) {

 this.suppressedExceptions = null;

 //移除缓存中对该bean正在加载的状态

 afterSingletonCreation(beanName);

 if (newSingleton) {

 //将新创建的bean加入缓存,并且删除加载bean过程中所记录的各种辅助状态

 //这些辅助状态主要是在回调方法创建bean时候引入的

 addSingleton(beanName, singletonObject);

 return (singletonObject != NULL_OBJECT ? singletonObject : null);

 }

现在继续去找创建bean的回调方法


//创建完的beanInstance还不一定不是我们最终需要的bean 还需要加工验证正确性 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

createBean方法里面还是在做一些准备工作,真正的创建bean交给了doCreateBean


@Override

 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {

 if (logger.isDebugEnabled()) {

 logger.debug("Creating instance of bean " + beanName + "");

 RootBeanDefinition mbdToUse = mbd;

 //根据指定的BeanDefinition信息 解析bean class 并且存储在BeanDefinition中

 Class ? resolvedClass = resolveBeanClass(mbd, beanName);

 //对已有的bean definition进行克隆 以防一动态解析的class不能存储在合并的bean definition中 

 //这里说的动态解析的class是指在bean class的定义中使用EL表达式或者自己定义的beanExpressionResolver

 if (resolvedClass != null !mbd.hasBeanClass() mbd.getBeanClassName() != null){

 mbdToUse = new RootBeanDefinition(mbd);

 mbdToUse.setBeanClass(resolvedClass);

 try {

 //验证及准备覆盖的方法

 mbdToUse.prepareMethodOverrides();

 catch (BeanDefinitionValidationException ex) {

 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),

 beanName, "Validation of method overrides failed", ex);

 try { 

 //给beanPostProcessors一个机会返回代理来替代真正的实例 

 //这里的beanPostProcessors是指InstantiationAwareBeanPostProcessor类型

 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

 if (bean != null) {

 return bean;

 catch (Throwable ex) {

 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,

 "BeanPostProcessor before instantiation of bean failed", ex);

 //创建bean的过程又交给了doCreateBean,spring中以doxxx开头的方法就是真正干活的方法

 Object beanInstance = doCreateBean(beanName, mbdToUse, args);

 if (logger.isDebugEnabled()) {

 logger.debug("Finished creating instance of bean " + beanName + "");

 return beanInstance;

 }

在这里首先关注下AbstractBeanDefinition类的prepareMethodOverrides方法


 public void prepareMethodOverrides() throws BeanDefinitionValidationException {

 // Check that lookup methods exists.

 MethodOverrides methodOverrides = getMethodOverrides();

 if (!methodOverrides.isEmpty()) {

 for (MethodOverride mo : methodOverrides.getOverrides()) {

 prepareMethodOverride(mo);

 }

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {

 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());

 if (count == 0) {

 throw new BeanDefinitionValidationException(

 "Invalid method override: no method with name " + mo.getMethodName() +

 " on class [" + getBeanClassName() + "]");

 else if (count == 1) {

 // Mark override as not overloaded, to avoid the overhead of arg type checking.

 mo.setOverloaded(false);

 }

spring配置中存在lookup-method和replace-method两个配置功能,这两个配置的加载就是将配置存储在BeanDefinition中的methodOverrides属性里面。功能的实现原理是在bean的实例化的时候如果检测到存在methodOverrides属性,会动态的为当前bean生成代理并使用对应的拦截器为bean做增强处理。

下一篇继续从doCreateBean说起。


虾皮二面:Spring Bean 默认是单例的,如何保证并发安全? Spring 的 Bean 默认都是单例的,某些情况下,单例是并发不安全的,以 Controller 举例,问题根源在于,我们可能会在 Controller 中定义成员变量,如此一来,多个请求来临,进入的都是同一个单例的 Controller 对象,并对此成员变量的值进行修改操作,因此会互相影响,无法达到并发安全(不同于线程隔离的概念,后面会解释到)的效果。 首先来举个例子,证明单例的并发不安全性:
Spring 源码阅读 25:单例 Bean 实例的创建过程(2) 通过本文的分析,终于走到了 Spring 最终把 Bean 实例创建出来的,这个实例会被一个 BeanWrapper 类型的对象包装,并返回到`doCreateBean`方法中。
Spring 源码阅读 17:初始化非懒加载的单例 Bean 本文分析 Spring 上下文初始化过程中, 提前初始化非懒加载的单例 Bean 的过程。这一步算是在容器初始化是进行的创建 Bean 的预热工作。
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Spring是如何解决循环依赖?
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载