首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

算法与数据结构体系课|完结无密

算法与数据结构体系课|完结无密

下载看水印

这段代码的作用是在实例化Bean之前进行处理。它检查Bean是否需要被代理:

如果需要,根据自定义目标源创建代理对象,并返回代理对象;

如果不需要代理或者不存在自定义目标源,则直接返回 null,即走正常的 bean 实例化逻辑;

它主要是用来在更灵活的创建代理目标的,一般我们并不会用到,因此这里了解即可。

1.2.作为早期引用被创建时

SmartInstantiationAwareBeanPostProcessor 提供了三个方法,AbstractAutoProxyCreator 实现了两个:

predictBeanType :确认 bean 的类型,这里会直接获取代理对象的类型;

getEarlyBeanReference :获取对象早期引用,这里会通过 wrapIfNecessary 尝试为 bean 创建代理对象;

在开始前,我们需要明确,什么是早期引用

一般情况下,Spring 会在 bean 初始化完毕后才会基于该 bean 实例创建代理对象,但是在循环引用时,比如 beanA 依赖 beanB 依赖 beanA 的情况下,由于后创建的 beanB 需要依赖先创建的 beanA,而在此时先创建的 beanA 并未完成初始化,则此时后创建的 beanB 会通过一级缓存中的 ObjectFactory ,也就是 () getEarlyBeanReference 方法提前获得基于 beanB 创建的代理对象(如果不需要代理则就是 beanA 本身),这就是早期引用。

不过,虽然是早期引用阶段,但是实际上在这里创建代理对象的逻辑是与正常的初始化后创建代理对象的逻辑基本一致的:

java复制代码public Object getEarlyBeanReference(Object bean, String beanName) {  Object cacheKey = getCacheKey(bean.getClass(), beanName);  this.earlyProxyReferences.put(cacheKey, bean);  return wrapIfNecessary(bean, beanName, cacheKey); }

后文我们需要重点关注 wrapIfNecessary 方法,不过目前我们知道在这一步会创建代理对象即可。

1.3.在初始化阶段

SmartInstantiationAwareBeanPostProcessor 提供了两个方法,AbstractAutoProxyCreator 只实现了其中的 postProcessBeforeInstantiation ,在初始化前,它将为 bean 生成代理对象:

java复制代码public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {  if (bean != null) {  Object cacheKey = getCacheKey(bean.getClass(), beanName);  // 如果在早期阶段已经创建过了,就不必再创建一次了  if (this.earlyProxyReferences.remove(cacheKey) != bean) {  return wrapIfNecessary(bean, beanName, cacheKey);  }  }  return bean; }

与 getEarlyBeanReference 基本一致,都是基于 wrapIfNecessary 完成的,只不过是时机不同。正常需要代理的 bean 会在这里被替换为代理对象。

2.创建代理对象前的准备

知道了代理对象在何时被创建,也大概了解了相关的基本组件,现在我们需要真正的了解代理对象是如何被创建的,通知、切点和通知器这些组件将会在这个过程中扮演怎样的角色。

而 wrapIfNecessary 方法则是入口,在这个方法中,spring 会确认 bean 是否需要被代理,如果是就为其创建代理对象:

java复制代码protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {  // 指定的目标源的对象不需要再代理(因为在初始化阶段就处理完了)  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {  return bean;  }  // 已经被代理则不需要再代理  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {  return bean;  }  // 如果是基础设施类,或者需要跳过就不代理  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {  this.advisedBeans.put(cacheKey, Boolean.FALSE);  return bean;  }   // 为 bean 获取需要的通知器  // Create proxy if we have advice.  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);  if (specificInterceptors != DO_NOT_PROXY) {  // 注明该 bean 已经被代理  this.advisedBeans.put(cacheKey, Boolean.TRUE);  // 为其创建代理  Object proxy = createProxy(  bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));  this.proxyTypes.put(cacheKey, proxy.getClass());  return proxy;  }   this.advisedBeans.put(cacheKey, Boolean.FALSE);  return bean; }

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O2zVueGc42O9Frbu1EF7ur0A0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券