上篇文章,我在开头将bean实例化过程比喻成寒武纪生命大爆发。如果你同意这个看法的话,那本文解析的bean的依赖注入就是生命的形式生物从两栖进化到爬行,从爬行进化到哺乳,从哺乳进化到类人猿,从低等进化到高等的过程。
本文撰写累计时常10小时,建议阅读时间5小时。去趟卫生间,等你回来我们就开始吧。
目录
1. applyMergedBeanDefinitionPostProcessors
1.1 CommonAnnotationBeanPostProcessor
1.2 AutowiredAnnotationBeanPostProcessor
3.1 CommonAnnotationBeanPostProcessor方法的inject
3.2 AutowiredAnnotationBeanPostProcessor方法的inject
上一篇文章,已经详细分析了bean的实例化过程。也就是doCreatBean方法中instanceWrapper = createBeanInstance(beanName, mbd, args);执行完成,将实例化后的bean封装在了wrapper中。随后再解封出来bean对象和bean对应的类型。接下来调用applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);方法。
1. applyMergedBeanDefinitionPostProcessors
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 从BeanWrapper获得封装在它内部的bean和bean类型
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 调用实现了MergedBeanDefinitionPostProcessor的bean后置处理器的postProcessMergedBeanDefinition方法。
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new xxx;
}
// 标记该bd已经合并处理完成了
mbd.postProcessed = true;
}
}
// 加入到bean工厂的earlySingletonObjects中,这个是Spring用来解决循环依赖的凭据(后续文章单独介绍循环依赖)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
// 依赖注入填充属性
populateBean(beanName, mbd, instanceWrapper);
// bean属性填充完成后,就可以进行bean的初始化工作了。依赖注入初始化工作后续文章再详细介绍。
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
throw new xxx;
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new xxx;
}
}
}
}
// 注册实现了DisposableBean接口的bean,该bean实现了void destroy()接口,在bean的生命周期销毁前可以触发回调进行善后工作。
// 需要注意的是,它对原型对象无效。
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new xxx;
}
return exposedObject;
}
调用实现了MergedBeanDefinitionPostProcessor的bean后置处理器的postProcessMergedBeanDefinition方法,其中有用到的后置处理器是CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor, ApplicationListenerDetector。
1.1 CommonAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法如下:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// 解析bean属性上@Resource的注解,将其封装为metadata对象并缓存
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
// 对注入的metadata对象进行检查,没有注册的bd需要进行注册。最后添加到metadata对象的checkedElements集合中。
metadata.checkConfigMembers(beanDefinition);
}
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);中处理@PostConstruct 和 @PreDestroy方法添加到InitDestroyAnnotationBeanPostProcessor的lifecycleMetadataCache这个CurrentHashMap中,该map中的存放的结果是<Class<?>, LifecycleMetadata>。LifecycleMetadata对象中封装了initMethods和destroyMethods方法,与之对应的是@PostConstruct 和 @PreDestroy注解的两类方法。通过class类名就能得到该声明周期回调对象。
metadata.checkConfigMembers(beanDefinition);对注入的medadata对象进行检查,没有注册的bd需要进行注册。最后添加到metadata对象的checkedElements集合中。
核心代码是findResourceMetadata(beanName, beanType, null);
InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 缓存中如果没有,则创建一个metadata
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildResourceMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
它的核心是buildResourceMetadata(clazz);它会沿着类及其父类解析出添加了@WebServiceRef, @EJB, @Resource注解的属性和方法,将其加入到elements中。然后将clazz和elements封装成一个InjectionMetadata对象findResourceMetadata方法。findResourceMetadata会将metadata对象缓存在commonAnnotationBeanPostProcessor后置处理器对象的injectionMetadataCache map中方便后续流程使用。
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
// 沿着class的继承路径,按层次寻找加上了@WebServiceRef, @EJB, @Resource注解的属性和方法,将其加入到currElements中。
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 遍历Class中的所有field,判断每个field是否需要被注入
// 如果上述注解加在静态类,静态方法,会直接报错!
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
currElements.add(new ResourceElement(field, field, null));
}
}
});
// 遍历Class中的所有method,判断每个method是否需要依赖项
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
//new的是一个ResourceElement实例,它是InjectionMetadata.InjectedElement的子类
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
// 将上面找到的currElements添加到elements中。
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
1.2 AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法如下,核心方法是findAutowiringMetadata。
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 缓存中如果没有,则创建一个metadata
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
与findResourceMetadata中核心方法是是调用buildResourceMetadata类似,在findAutowiringMetadata中核心方法是调用buildAutowiringMetadata。最终也会将需要注入的属性或方法添加到elements中。并且返回封装好的metadata对象。上层也会将其缓存到injectionMetadataCache中。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 遍历Class中的所有field,根据注解判断每个field是否需要被