IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring源码分析-Bean生命周期查找与注册(2) -> 正文阅读

[Java知识库]Spring源码分析-Bean生命周期查找与注册(2)

Spring源码分析系列

Spring源码分析-启动流程浅析
Spring源码分析-Spring源码分析-BeanDefinition
Spring源码分析-Bean生命周期概述
Spring源码分析-Bean生命周期查找与注册
Spring源码分析-Bean生命周期查找与注册(2)



前言

bean的生命周期是重要的知识点,为了能记住这几篇博客都会反复提醒,具体如下:
实例化 --> 属性赋值 --> Bean后置处理器before方法 --> 属性处理器afterProtpertiesSet --> 初始化方法init-method --> Bean后置处理器after方法 --> 对象应用 --> 销毁方法destroy-method --> gc回收。
本篇博客将进一步分析,bean获取与注册流程


一、getBean

spring一共提供三个getBean重载方法,具体声明如下

public Object getSingleton(String beanName)
protected Object getSingleton(String beanName, boolean allowEarlyReference)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)

前两个只用于查找,第三个可以用于注册

1.1、查找

下面的代码注释很详细,分别从一级缓存,二级缓存,三级缓存中进行查找,直到找到为止

@Override
@Nullable
public Object getSingleton(String beanName) {
	return getSingleton(beanName, true); //调用重载方法
}

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    // 不加锁的原因是快速查找
    Object singletonObject = this.singletonObjects.get(beanName); //一级缓存获取实例
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        singletonObject = this.earlySingletonObjects.get(beanName); //二级缓存
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                // Consistent creation of early reference within full singleton lock
                singletonObject = this.singletonObjects.get(beanName);//一级缓存
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);//二级缓存
                    if (singletonObject == null) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); //三级缓存,获取ObjectFactory,实际上是一个lamda表达式
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();//获取对象
                            this.earlySingletonObjects.put(beanName, singletonObject);//放到二级缓存中
                            this.singletonFactories.remove(beanName);//从三级缓存中删除
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

1.2、注册

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {//加锁操作
        Object singletonObject = this.singletonObjects.get(beanName); //从一级缓存中获取bean对象
        if (singletonObject == null) {//当前bean不存在
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName,
                        "Singleton bean creation not allowed while 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 + "'");
            }
            beforeSingletonCreation(beanName);//标志当前beanName是在正在创建,本质上是插入到set集合中
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                singletonObject = singletonFactory.getObject(); //本质上是执行lamda表达式,创建对象,当返回后bean对象创建完成
                newSingleton = true; //单例
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                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;
                }
                afterSingletonCreation(beanName);//将当前正在创建的bean从set集合中删除
            }
            if (newSingleton) {
                addSingleton(beanName, singletonObject);//放到一级缓存中
            }
        }
        return singletonObject;
    }
}

注意方法的第二个参数是一个lamda表达式,lamda表达式内容如下:

sharedInstance = getSingleton(beanName, () -> {
	try {
		return createBean(beanName, mbd, args); //创建bean对象,底层通过反射方式
	}
	catch (BeansException ex) {
		// Explicitly remove instance from singleton cache: It might have been put there
		// eagerly by the creation process, to allow for circular reference resolution.
		// Also remove any beans that received a temporary reference to the bean.
		destroySingleton(beanName);
		throw ex;
	}
});

创建完bean对象,要将bean插入到一级缓存,并且从二级,三级缓存中移除掉

protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		this.singletonObjects.put(beanName, singletonObject);//放到一级缓存中
		this.singletonFactories.remove(beanName); //从三级缓存中删除
		this.earlySingletonObjects.remove(beanName); //从二级缓存中删除
		this.registeredSingletons.add(beanName); //插入到set中
	}
}

二、getObjectForBeanInstance

当我们从缓存中获取到bean对象,这个bean对象可能是FactoryBean,并不是我们实际要用的对象

2.1、源码

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, 
                                    @Nullable RootBeanDefinition mbd) {

    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    // 判断是否是间接引用的FactoryBean, 名字是以&开始
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        return beanInstance;
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    if (!(beanInstance instanceof FactoryBean)) {//说明当前对象没有实现FactoryBean接口,所以可以直接返回给应用使用
        return beanInstance;
    }
    //进入下面分支表示一定是FactoryBean
    Object object = null;
    if (mbd != null) {//创建FactoryBean对象本身时,会进入
        mbd.isFactoryBean = true;
    }
    else {//第一次查缓存,对象肯定不存在,如果是单例模式,第一次创建成功后保存到缓存中,以后在获取就不会创建对象
        object = getCachedObjectForFactoryBean(beanName); //从缓存factoryBeanObjectCache中取出
    }
    if (object == null) {//表示缓存没有,则创建对象
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic); //调用FactoryBean接口中的getObject返回真实实例对象
    }
    return object;
}

2.2、例子

spring代码大部分接口都自己的抽象类,我们可以直接继承抽象类,并将其注入到spring ioc容器中

@Component
public class FactoryBeanUser extends AbstractFactoryBean<User> {
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

    @Override
    protected User createInstance() throws Exception {
        User user = new User();//创建对象
        user.setUsername("xuxb");
        return user;
    }
}

上面创建一个FactoryBean并且注入到spring容器中,接下来获取一下这个bean:

public static void main(String[] args) {
     try {
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.worker");
         Object o1 = context.getBean("factoryBeanUser");
         System.out.println("o1="+o1);
         Object o2 = context.getBean("factoryBeanUser");
         System.out.println("o2="+o2);
         context.registerShutdownHook();
     } catch (Exception e) {
         System.out.println(e);
     }
 }

输出内容

> Task :spring-study-01:WApp.main()
o1=com.worker.User@10a035a0
o2=com.worker.User@10a035a0
BUILD SUCCESSFUL in 6s

从上面内容可知
1、注入的类型的是FactoryBeanUser,而得到的类型是User
2、每次获取bean对象都是同一个(地址相同),第一次创建成功后就缓存起来了


三、总结

本篇博客,介绍了getBean方法处理逻辑,它是spring框架中一个核心代码,理解它有助于理解spring对bean的管理方式。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-01 20:27:55  更:2022-02-01 20:28:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:01:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码