spring的getBean()方法
2022-11-18 21:06:32 0 举报
主要是getBean()的内部源码细节 比较细节,可以跟着线路看一下代码
作者其他创作
大纲/内容
createBeanInstance()
BeanPostProcessor的postProcessAfterInitialization()方法
结束
获取待装配属性populateBean()
getBean(beanName)
getBean()请看左上角,谢谢
getSingleton()
4、使用默认构造函数构造
bean
内置了专门处理SmartInstantiationAwareBeanPostProcessor类型的增强器
2,通过工厂方法实例化
ApplicationListenerDetector检测bean是否实现了ApplicationListener接口
到此,bean的一些基本属性和引用的属性都填充好了,下面的算是扩展了
一级缓存没找到,判断bean是否正在创建中
结束return
都满足
同名的方法,参数不一样的,是两个不一样的方法
主要感知这几个的set方法
其他的模式,没有立即走createBean逻辑,而是创建一个引用,后面get的时候再调用
自动注入:包括名称注入和类型注入。不推荐使用,只支持 XML 配置方式
类似
注意这个时候,beanName是没有带着&的,所以得到的结果就是getObject返回的结果猜测这个判断目的就是智能急切的初始化我们想要的bean
假如上面返回的自定义类型还没有 创建则
循环调用
EnvironmentAwareEmbeddedValueResolverAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAwareApplicationContextAware
查不到对象则进行创建
applyPropertyValues()
如果从缓存中拿到对象
过滤InstantiationAwareBeanPostProcessor类型的BeanPostProcessor,别的不执行
做一些权限等校验得到Method对象
doCreateBean()
如果bean是单例的并且实现了ApplicationListener接口,则加入到多播器中applicationEventMulticaster。
返回一个包装wrappedBean
从一级缓存里面查找Object singletonObject = this.singletonObjects.get(beanName);
null
BeanDefinitionValueResolver.resolveValueIfNecessary()
内部逻辑
这里对接一下refresh() .finishBeanFactoryInitialization()方法。
从一级缓存中再查一下Object singletonObject = this.singletonObjects.get(beanName);
BeanUtils#instantiateClass
循环处理dependsOn的bena
必须实现SmartInitializingSingleton接口afterSingletonsInstantiated()方法
AOP相关的
执行每个的postProcessAfterInstantiation()方法
1,通过Supplier实例化
检查当前bean是否正在销毁,如果是抛出异常
返回
xml中只注册一个FactoryBean类型的bean,则spring容器中,只有一个工厂bean
getObjectForBeanInstance()
1、是单例 2、允许循环依赖 3、指定的单例bean当前是否在创建中
doGetObjectFromFactoryBean()
马上就要实例化Bean了根据beanName确保beanClass被加载了
** 继承InstantiationAwareBeanPostProcessorAdapter、实现 MergedBeanDefinitionPostProcessor 是为了根据后处理器的调用时机来完成一些功能。** 实现 PriorityOrdered 接口是为了标注自身优先注入。** 实现 BeanFactoryAware 是为了拿到 BeanFactory。
如果是原型模式,就是不放进缓存了,直接调用createBean()方法,逻辑一样
判断是否实现FactoryBean接口
判断是不是RuntimeBeanReference类型,然后走getBean()流程
newSingleton = true;
默认内置的
1、在 xml配置中,可以使用 factory-bean 和 factory-method 两个标签可以指定一个类中的方法,Spring会将这个指定的方法的返回值作为bean返回(如果方法是静态方法,则可以不创建factory-bean就直接调用,否则需要先将factory-bean注入到Spring中)
invokeAwareMethods
调用父类的方法最终
对于销毁方法的扩展,除了destroy-method属性外,还可以注册后处理器DestructionAwareBeanPostProcessor来统一处理bean的销毁方法
singletonObject = singletonFactory.getObject();调用参数的方法,其实执行的是createBean方法
注入完成,结束
// 获取实例化策略InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
依赖检查检查要注入的依赖是否已经完整。可以只检查简单类型(Java 原生类型、Enum、Class 等),也可以只检查对象类型
private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<>(\"Prototype beans currently in creation\");
就是refresh的最后一个方法
到此其实一个完成的bean怀胎十月可以出生了
ConstructorResolver#autowireConstructor
是
工厂bean才有的逻辑
简单来说,就是根据传入的参数列表,来匹配到合适的构造函数进行bean 的创建。1、解析构造函数参数。 2、获取候选的构造函数列表。 3、解析构造函数参数个数。4、寻找最匹配的构造函数
getObjectForBeanInstance()方法。Spring为何要如此做,原因是因为当Spring无论从哪种方式,哪种scope获取Bean实例之后,都需要对这个Bean进行检查其是否是FactoryBean<?>类型,如果这个Bean是FactoryBean类型,则需要回调FactoryBean接口中定义的三个方法进行初始化开发者实现FactoryBean接口对特殊Bean实施的高级定制初始化逻辑。
BeanFactoryUtils.isFactoryDereference(name)就是beanName以&开头
主要两种 SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy,简单实例化策略(直接反射) 和 Cglib 动态代理策略(通过cglib 代理),默认第二种。注:CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy
有一段getParentBeanFactory处理的逻辑,就是委托给父工厂的处理,先不追究
boolean newSingleton = false;
手动注入
ApplicationContextAwareProcessor
研究了再补充
否
进入内部分方法
org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
调用BeanPostProcessor的postProcessBeforeInitialization方法。
尽早初始化 LoadTimeWeaverAware bean,以便尽早注册它们的转换器。先初始化 LoadTimeWeaverAware 类型的 Bean. aop相关 注:大概有个印象,以后解析aop会和它串起来
主要是判断缓存里面是否存在,然后创建,放进缓存
首先从缓存中拿实例Object sharedInstance = getSingleton(beanName);
InitializingBean接口的afterPropertiesSet()方法
直接返回,当前工厂bean的实例
instantiateWithMethodInjection()调用cglib的方法创建
是在创建中
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
根据反射调用methodToInvoke.invoke(bean);
无参构造
做一个校验,是否实现FactoryBean接口,是否不为空,否则抛出异常
仅仅处理set这几个到我们的bean中,如果需要:BeanNameAwareBeanClassLoaderAwareBeanFactoryAware
3,用合适的构造函数实例化- autowireConstructor()
afterSingletonCreation(beanName);//bean创建完成后singletonsCurrentlyInCreation要删除该bean
getObjectFromFactoryBean()
如果bean 不为null
正常情况下,当前bean和依赖的属性假如有bean的 都在容器中创建了下面就就行属性的关联填充了
ConfigurationClassPostProcessor处理注解的,不太清楚
String beanName = transformedBeanName(name);
执行getBeanPostProcessors的postProcessAfterInitialization
判断当前bean是否实现SmartFactoryBean
invokeInitMethods()
如果RootBeanDefinition 中存在 factoryMethodName 属性,或者在配置文件中配置了factory-method,Spring会尝试使用 instantiateUsingFactoryMethod 方法,根据RootBeanDefinition 中的配置生成bean实例。
init-method指定的方法
调用指定的getSingleton方法,参数类型为一个ObjectFactory<?>的lamda表示式,里面包含一个createBean方法
Supplier方式比较简单,instanceSupplier.get()回调到自己定义的函数里面返回一个实例对象然后包装成BeanWrapperImpl返回就行了。
initializeBean()初始化
过滤掉基本属性和过滤掉没有set方法的自定义类型,ignoredDependencyInterfaces定制忽略的,spring内部忽略的一些aware的类型的接口,在这个地方注入,
循环每一个banName
\"&\"+beanName
不管哪个模式,创建就完成,并且走完小重点
//循环依赖检查,判断是否需要抛出异常
到此还没有正式的执行创建bean的核心代码,上面的都是花里胡哨的扩展
下面为循环依赖预处理
继续往下,处理当前的bean
如果是通过自定义工厂创建bean,其实是beanName写的工厂的名字,但是返回类型是自己的context.getBean(\"myFatoryBean2\
先判断beanName是否以&开头
2、对@Bean 注解的解析。在 ConfigurationClassPostProcessor 后处理器中,会对被 @Bean 注解修饰的方法进行解析,生成一个 ConfigurationClassBeanDefinition的 BeanDefinition。此时BeanDefinition 的 factoryMethodName 正是 @Bean修饰的方法本身。所以这里会调用 instantiateUsingFactoryMethod 方法。通过回调的方式调用 @Bean修饰的方法。并将返回结果注入到Spring容器中
beanFactory.preInstantiateSingletons();
ConstructorResolver#instantiate()
if (!bd.hasMethodOverrides()) {
处理 @Autowired 和 @Value 等注解,Spring 提供 ibp#postProcessProperties 可以调整 bean 实例。如 AutowiredAnnotationBeanPostProcessor 用于处理 @Autowired 和 @Value 注解。CommonAnnotationBeanPostProcessor 用于处理 @Resource 注解
这个接口一般不建议自己去实现用,spring内部的实现类有1、CommonAnnotationBeanPostProcessor 2、AutowiredAnnotationBeanPostProcessorBeanPostProcessor接口的典型运用,这里要着重理解这个接口对类中注解的自动装配过程,这里是非常重要的一个分支
从缓存Map变量中取一下factoryBeanObjectCache
factory.getObject()
触发回调,只针对于单例对象
判断bean是否是原型模式,且有循环依赖,如果是抛出异常
可以看到和循环依赖的检测判断有些似曾相识,都是通过正在创建中的集合来判断的,也就是创建时记录和检查,这里是通过 prototypesCurrentlyInCreation 这个 ThreadLocal 来进行记录相关的创建中原型集合的,而这个记录则是在 beforePrototypeCreation(String beanName) 和 afterPrototypeCreation(String beanName) ,这个可以在稍后面的原型实例化创建时看到有相关调用,这里的默认实现就是直接将 beanName 丢到 prototypesCurrentlyInCreation 中。
如果是单列模式
初始化所有剩下的非懒加载的单例bean 启动tomcat
beforeSingletonCreation(beanName);把beanName添加到singletonsCurrentlyInCreation Set容器中,在这个集合里面的bean都是正在实例化的bean
继续当前方法的下面逻辑
注解注入
假如bean已经实例化,第二次请求的时候,好判断,但是第一次请求还没有实例,只能解析class,然后进行复杂的判断FactoryBean
//根据名称自动注入.
SimpleInstantiationStrategy. instantiate()
如果使用了aop代理,那么此处会生成代理对象,替换原生bean对象。
自定义创建bean实例的方法
内部方法
String[] dependsOn = mbd.getDependsOn();
循环上面的结果getBean()
得到一个BeanWrapper,携带创建好的bean实例
getBean()
ConstructorResolver类1、instantiateUsingFactoryMethod()
// 这里主要处理@Lookup注解,进行方法的替代!mbdToUse.prepareMethodOverrides;
最先初始化名字为 conversionService的类,conversionService类它用来将前端传过来的参数和后端的 controller 方法上的参数进行绑定的时候用尤其是用于非基础类型的转换
加入了后置的增强器,来增强属性-->>>AutowiredAnnotationBean.PostProcessorpostProcessProperties()
上面两种执行各自的寻找的逻辑
得到MutablePropertyValues封装属性的对象
处理增强器的逻辑MergedBeanDefinitionPostProcessor接口子类
注册bean销毁时的类DisposableBeanAdapter
autowire只是针对自定义对象类型的吧?
1、解析对象:委托 BeanDefinitionValueResolver 完成。2、类型转换:委托 TypeConverter 完成。3、属性注入:委托 bw 完成。4、结果缓存:applyPropertyValues 方法本身完成的最大功能
得到所有的bean定义,这些可能包括上面的的一些增强器,已经初始化到spring容器里面,后面会从缓存里面获取,等一些判断,就不会再走一遍创建bean的所有流程
doGetBean()
从二级缓存里面取singletonObject = this.earlySingletonObjects.get(beanName);
实例化后执行注册的处理器中的方法(如果有的话),如果返回了false,则不进行属性装配,直接返回// 在设置属性之前,让任何 InstantiationAwareBeanPostProcessors 有机会修改 bean 的状态。例如,这可用于支持字段注入样式。
// 将bean 标记为已创建或即将创建markBeanAsCreated(beanName);变量private final Set<String> alreadyCreated
所以只有单例的情况才能使用循环依赖,其他情况spring不支持
这个时候已经开始预初始化, bean 定义解析、加载、注册先停止
beanFactory.freezeConfiguration();
执行postProcessMergedBeanDefinition()
现在明确知道类型是FactoryBean,强转(FactoryBean) beanInstance
createBean()
if (sharedInstance != null && args == null) {
处理可能多个InstantiationAwareBeanPostProcessors
bean==null
得到lamda表达式创建bean的方法
AbstractAutoProxyCreator
有参构造
假如这个时候,加入了注解,就要解析每个上面的注解,然后构造成set这样的方式到pvsToUse属性里面
protected BeanWrapper autowireConstructor()
处理当前bean的依赖,保证它依赖的bean都被初始化
反射---return ctor.newInstance(argsWithDefaultValues);
开始遍历List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
bean模式分情况处理
从三级缓存里面找ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
自己写的
做一个最后的类型检查和类型强转
不为null 直接返回
如果有父工厂
判断bean是不是工厂bean
进入DefaultSingletonBeanRegistry#getSingleton()
instantiateBean()
0 条评论
下一页