“’ to allow for resolving potential circular references”);
}
该方法 是解决循环依赖; 循环依赖将放在下个篇章去讲;
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
这时候 开始了Bean的属性注入;
Object exposedObject = bean;
try {
这个方法 是主要方法;
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
以下源码全部省去; 进入populateBean里面去看看;
}
===========================================================================
@SuppressWarnings(“deprecation”)
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
按照惯例 先隐藏前面代码; 方便阅读;
前面有说道 会先去拿它的PropertyDescriptor 这个东西是什么作用的 自己去看上面的我写的案例;
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
循环当前Bean的 BeanPostProcessor BP
在5.3.5 版本有6个 其他版本可能个数会不一样
主要的一个BP 是 : AutowiredAnnotationBeanPostProcessor
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
隐藏后面代码
这个for循环这个List给你们打印出来
在通过了这个bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
会往BeanWrapper.getWrappedInstance() 这里 保存的值 的内存引用 就是单例池里面的相对应需要注入的哪个Bean. 所以 这里将他注入; 那么外面哪个Bean里面就有值了;
AutowiredAnnotationBeanPostProcessor
================================================================================================
postProcessProperties
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
顾名思义; 应该可以知道这个方法里面是在做些什么事情;
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
依赖注入核心方法;
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, “Injection of autowired dependencies failed”, ex);
}
return pvs;
}
==================================================================
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
这个源码熟吧? 里面的InjectedElement 放着就是 你依赖注入的每一个属性;
Collection checkedElements = this.checkedElements;
Collection elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
inject2 进入这个inject的时候要注意; 是这个;
==========================================================================================
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
filed就是我们要注入的属性;
Field field = (Field) this.member;
Object value;
检查缓存
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
value = resolveFieldValue(field, bean, beanName);
}
}
else {
如果没有缓存的情况下 走resolveFieldValue
value = resolveFieldValue(field, bean, beanName);
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
=============================================================================
=================================================================================
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
传入之后 先看你的required 是否为false;
在Autowired 里面的那个required 表示是否一定要注入;默认为true
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, “No BeanFactory available”);
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
通过这个步骤找到了 value
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
------省掉部分代码
返回这个value;
return value;
}
}
==============================================================
==================================================================
在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor的 **postProcessMergedBeanDefinition()**找出注入点并缓存,找注入点的流程为:
-
遍历当前类的所有的属性字段Field
-
查看字段上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该字段 是一个注入点
-
如果字段是static的,则不进行注入
-
获取@Autowired中的required属性的值
-
将字段信息构造成一个AutowiredFieldElement对象,作为一个注入点对象添加到 currElements集合中。
-
遍历当前类的所有方法Method
-
判断当前Method是否是桥接方法,如果是找到原方法
-
查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法 是一个注入点
-
如果方法是static的,则不进行注入
-
获取@Autowired中的required属性的值
-
将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到 currElements集合中。
-
遍历完当前类的字段和方法后,将遍历父类的,直到没有父类
-
最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合 对象,并缓存。
==============================================================================
我们假设:
在属性中 我们的Bean是原型Bean 也就是多例的 那么 他属性如果用了static会怎么样? 这个问题如果想明白了 就知道为什么不支持了.
在static修饰的方法中 其字节码文件会生成两个同样的方法 其中一个方法带有 synthetic bridge 并且都是存在@Autowired注解的 所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法
===================================================================
Spring在AutowiredAnnotationBeanPostProcessor的**postProcessProperties()**方法中,会遍 历所找到的注入点依次进行注入。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
总结
大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。
麻烦帮忙转发一下这篇文章+关注我
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
对你有帮助,可以添加V获取:vip1024b (备注Java)**
[外链图片转存中…(img-oUMOfq9k-1712674986386)]
总结
大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。
麻烦帮忙转发一下这篇文章+关注我
[外链图片转存中…(img-hzbbvXtn-1712674986386)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-VzFECazB-1712674986387)]