Spring getBean 要点记录。

getBean流程

  1. 先 sharedInstance = getSingleton(String beanName) 来获取 单例的bean。
  2. 获取不到 再sharedInstance = getSingleton(String beanName, ObjectFactory<?> singletonFactory) 自己传个匿名内部类。
    2.1 singletonObject = singletonFactory.getObject(); 调用匿名内部类的getObject 也就是createBean(beanName, mbd, args);
    2.2 加到 addSingleton(beanName, singletonObject); 这里 一级缓存加进去,二级、三级移除,registeredSingletons (已注册bean)中添加,Set 类型的 。
  3. 看 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)的流程。
    3.1 一堆校验 然后 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) ;
    3.2 earlySingletonExposure(是否提前暴露,是单例并且正在创建)的情况,addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));,又是一个匿名内部类。一级缓存不存在就移除二级缓存,并添加三级缓存(就是传进来匿名内部),并 registeredSingletons (已注册bean)中添加。
    3.3 populateBean(beanName, mbd, instanceWrapper); 填充bean。这里如果引用了其他的Bean就回可能导致循环依赖,就需要解决。
    3.4 initializeBean 初始化bean。
    3.5 再判断 是否提前暴露。是的话Object earlySingletonReference = getSingleton(beanName, false); 从一级中拿拿不到从二级缓冲中拿,返回。
sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						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;
						}
					});
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);
		}
	}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

三级缓存解决循环依赖

earlySingletonObjects 和 singletonFactories 永远是互斥的。

DefaultSingletonBeanRegistry  类中属性。
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** Set of registered singletons, containing the bean names in registration order. */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

singletonFactories put时机。 三级

  1. getBean的第二次 getSingleton(String beanName, ObjectFactory<?> singletonFactory) ->
  2. 调用doCreateBean -> addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 这里的参数bean是上边Instance出来的bean实例 ->
  3. addSingletonFactory 里 this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName);
if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
		
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

earlySingletonObjects put时机。二级

  1. populateBean 第二个bean创建时调用 赋值参数里有 autowireByName(beanName, mbd, bw, newPvs);
  2. autowireByName(beanName, mbd, bw, newPvs); 里 Object bean = getBean(propertyName);
  3. 再次来到了 getBean的入口。又来到了 getBean的第一个 getSingleton(String beanName)
  4. 这里 return getSingleton(beanName, true); 传了个 true。后边要用到的。
  5. 这个 singletonObjects 取不到,earlySingletonObjects取不到 并且 singletonFactories取的到。那就。singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); 取到的bean 就是第一个beanaddSingletonFactory 把new的自己的Instance。 至此 二级缓存拿到bean了
  6. 自此 第二个bean就 能成功渠取到第一个bean。 而且getBean中走到第一个Object bean = getBean(propertyName);就能取到。

singletonObjects put时机 一级

  1. getBean的第二个 getSingleton(String beanName, ObjectFactory<?> singletonFactory) {}
  2. 里 会singletonObject = singletonFactory.getObject(); 触发createBean。
  3. 下一行代码就是 newSingleton = true;
  4. 最后的方法体会 if (newSingleton) { addSingleton(beanName, singletonObject); }
try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				一堆cache

if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}

具体创建bean的地方。

  1. 入口 doCreateBean
  2. instanceWrapper = createBeanInstance(beanName, mbd, args); 这里就会创建bean了。并返回一个包装Wrapper。
    2.1. 根据 RootBeanDefinition类型的 mbd判断是不是有FactoryMethod有的话选择 Factory的形式来创建bean。
    2.2 还有俩个策略 一个个根据有参构造来创建,一个是根据默认的无参构造啦实现。== Constructor 类型的 ctor.newInstance(argsWithDefaultValues)==
  3. doCreate 里会有 getEarlyBeanReference 包装bean为代理bean。这里就引申了Spring IOC 里的创建代理对象了,最关键的一行代码。获取到拦截器的链来创建代理。
Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

具体创建的俩个地方
JDK动态代理 :这个比较熟悉直接梳理,也比较简单。
创建入口JdkDynamicAopProxy类的getProxy 方法里,直接调用了JDK的方法,直接把this作为 InvocationHandler传进去了,那么所有JDK动态代理的对象都是JdkDynamicAopProxy的invoker来处理了。

/**public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
*/
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

Cglib代理:这个DeBug过看具体的Spring Bean实例也不陌生一堆Enhancer
创建入口CglibAopProxy类的getProxy 方法里,先Enhancer enhancer = createEnhancer();然后一堆设置属性最主要的属性enhancer.setCallbacks(callbacks);,一堆判断,最后enhancer.create()(有构造函数就是传构成函数的enhancer.create(this.constructorArgTypes, this.constructorArgs))。
简绍AOP有个不错的博客Spring源码剖析-拜托面试官别再问我AOP原理了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值