Bean的诞生(二)

Bean在经历了属性的注入后只剩下了它最后一步的拓展了,spring中既有BeanPostProcessor,也有各种Aware接口的回调.在最后将bean从容器取出来的过程,也不是轻轻松松就能完成的

Aware接口汇总

Aware接口是一个让bean获取spring的底层部件信息的一个接口,通过实现Aware接口的各种子接口,就可以获取到spring的各种底层信息了,那么Aware到底有多少个底层接口呢?在此列举一下
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware
据不完全统计,有这么多的Aware,这些Aware都是在bean实例化,属性注入好后去拓展的,这些拓展类能给予Bean包装.动态代理其实就是这样的一种包装思想,在获取bean之后,判定这个bean是否被代理了.如果被代理了,则会进入动态代理的处理逻辑中,最后返回使用的则是一个动态代理的对象,当然对于Spring的AOP将会在后续博客中去学习

Bean拓展源码

AbstractAutowireCapableBeanFactory的initializeBean方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					//实现Aware拓展接口的方法BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
					invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			//实现Aware拓展接口的方法BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//执行在之前实例化到容器中的BeanPostProcessor的postProcessBeforeInitialization方法,
			//ApplicationContextAwareProcessor中会对EnvironmentAware,EmbeddedValueResolverAware
			//ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware
			//这些Aware接口进行处理
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//如果实现了InitializingBean,则会执行InitializingBean的afterPropertiesSet()方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			//执行在之前实例化到容器中的BeanPostProcessor的postProcessAfterInitialization方法,
			//这里就是spring的Aop的入口
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

Bean循环依赖

bean的循环依赖主要是由于A类中注入类B,而类B中需要注入类A,在这样的情况下产生就会一直循环去getBean.在早期spring并没有解决这样的问题.一般是在会产生循环依赖的属性上加上**@Lazy的注解去解决,就是在getBean时判断下有没有这个注解,有的话会返回一个代理类来解决.在某一版本spring后,已经解决了spring的循环依赖的问题.spring解决问题的方法则是使用了三级缓存.个人感觉如果只是循环依赖,二级缓存也是可以解决的,然而spring使用的是三级缓存**,在此篇博客中曹工说Spring Boot源码(29)-- Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存有详细的说明,作者写的很棒!最后使用三级缓存是因为二级缓存虽然能够解决循环依赖的问题,但是却不能解决AOP中循环依赖时,注入的Bean是原始Bean而不是代理Bean的问题,因此使用了三级缓存.
三级缓存解决这个代理问题,就是第三季缓存中存入了一个工厂类,这个类在实际上会调用AbstractAutoProxyCreator类的getEarlyBeanReference方法,这样就能保证返回的是一个代理类了.
大体思路就是
1.初始化A
2.将初始化的A放入三级缓存
3.属性注入B
4.初始化B
5.属性注入A
6.从三级缓存中拿A
7.三级缓存使用了后置处理器并且最后会调用AbstractAutoProxyCreator的getEarlyBeanReference方法,通过初始化的A生成代理类
8.B完成实例化
9.A中属性注入成功
10.返回代理类A

代理A中的A属性也应该是随着A的实例化慢慢填充好了值

FactoryBean?

面试可能会被问到FactoryBean和BeanFactory有什么区别.其实他们从名字有点相似,都是接口以外,其实完全不是一个概念
BeanFactory是spring的容器啊,其中很多东西都是在BeanFactory中,它是最顶级的接口.
而FactoryBean只是我们实例化Bean的时候一种方法,一个类继承了FactoryBean接口,实现其getObject方法,就可以了,在取bean的时候可以直接通过这种形式去取,
如:A实现FactoryBean,实现其getObject方法返回一个B实例
当我们从容器中取A类时,会直接返回B实例
那怎么取A呢,取时名称前多加个"&"就可以了源码不难,不贴了,有兴趣可以看看

spring的IOC部分算是要告一段落了,后面会对spring的AOP源码进行学习总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值