【Spring源码系列- IOC】
本文目录
我们先来看看这个传说中的createBean()长什么样(*≧ω≦)~~
createBean()
进入createBean()后,先锁定class,根据设定的class属性或者根据className调用resolveBeanClass()方法来解析class resolveBeanClass()
-
第一步:判断入参的RootBeanDefinition的定义信息中是否包含BeanClass(注意是Class类型)
-
第二步:判断是否有安全管理器
-
第三步:执行详细的处理解析流程后返回
其实从上图可以看出,不管走不走安全管理器的安全检查都会执行doResolveBeanClass()来进行详细的处理解析流程
doResolveBeanClass()
方法中
-
获取Bean的加载器
- 获取bean的className
- 定期检查缓存BeanDefinition的结果
resolveBeanClass()
在获取到BeanName后,调用ClassUtils.forName来获取当前BeanName对应的Class对象
其本质还是在ClassUtils这个方法类中执行了Class.forName的操作来创建类
prepareMethodOverrides()
这是一个验证及准备覆盖的方法
再次进入prepareMethodOverride
这个方法先获取对应类中对应方法名的个数,没有的话抛出异常,只有1个则标记method Override暂未被覆盖(以避免参数类型检查的开销) 这里的方法覆盖主要涉及到lookup-method、replace-method这两个标签
-
当需要创建的bean对象中包含了lookup-method和replace-method标签的时候,会产生覆盖操作(后面会有一篇lookup-method标签的保姆级示例)
-
这里面用到了cglib,后面我们会有个案例详细解释,一般看到enhance就应该想到cglib
思考:为什么在Spring中会有那么多的cglib的使用?关于动态代理后面会有一篇详细来
执行继续往下
doCreateBean()
进入实际创建bean的实例的doCreateBean()
先创建一个用来持有bean对象的BeanWrapper,然后判断是否是单例对象,如果是单例对象,从factoryBean实例缓存中移除当前bean的定义信息,随后根据执行bean使用对应的策略创建新的实例(工厂方法、构造函数主动注入、简单初始化)
createBeanInstance()
-
首先需要通过调用resolveBeanClass()确认需要创建的bean实例的类可以实例化createBeanInstance();然后确保Class不为空,并且访问权限是public
-
再通过getInstanceSupplier()判断当前BeanDefinition中是否包含实例供应器(此处相当于一个回调方法,利用回调方案,来创建Bean)
函数式接口:supplier
-
判断工厂方法是否为空,不为空则使用工厂方法初始化策略(instantiateUsingFactoryMethod())
一个类中可能有多个构造器,所以Spring要根据参数个数、类型确定需要调用的构造器;在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或者过工厂方法保存在缓存中,避免再次创建相同Bean时再次解析,标记下,防止重复创建同一个Bean,有多个构造函数,每个构造函数都有不同的参数,所以调用前要先根据参数锁定构造函数或对应的工厂方法
instantiateBean()
实例化Bean
在获取到实例化策略后调用instantiate()方法进行实例化
instantiate()
判断在bd对象定义中,是否包含MethodOverride列表(Spring中有两个标签参数会产生MethodOverride(lookup-method(解决单例引用原型)、replace-method)会分为两种情况:
第一种情况:有MethodOverride,会调用instantiateWithMethodInjection()方法生成cglib的子类
CglibSubclassCreator(bd, owner)
首先定义了一个回调类型的数组CALLBACK_TYPES(后面的MethodOverrideCallbackFilter会通过指定下标获取对应的拦截)
CglibSubclassCreator(bd, owner).instantiate(ctor, args)
当前这个实例化的方法先根据BeanDefinition来调用createEnhancedSubclass()方法创建一个cglib的子类(对原始类进行增强)设置其各个属性,其中setCallbackTypes()方法对回调函数进行了拦截器的“指定”(此处使用了CglibSubclassCreator一开始定义的数组CALLBACK_TYPES)
第二种情况:没有MethodOverride,则会在获取到构造器后实例化
-
在实例化过程中,会先尝试获取被实例化对象的构造方法,如果没有,则尝试获取BeanClass,如果要实例化的BeanDefinition是个接口,则直接抛出异常,还会尝试获取系统安全管理器(如果有的话=[,,_,,]:3),未获取到则会使用默认的构造器
-
获取到构造器后,会将构造器赋值给bd中的属性
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135391.html