首页>>后端>>Spring->从源码层面带你实现一个自动注入注解

从源码层面带你实现一个自动注入注解

时间:2023-11-29 本站 点击:1

首先,需要了解到的是。Spring Bean 的生命周期

在生命周期中。注入bean属性的位置是在以下代码:populateBean 位置中

那么我们在项目中使用注解 产生一个bean的时候必定会经过以下代码进行一个bean的创建流程

/**省略代码**///开始初始化bean实例对象ObjectexposedObject=bean;try{//<5>对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性populateBean(beanName,mbd,instanceWrapper);//<6>调用初始化方法exposedObject=initializeBean(beanName,exposedObject,mbd);}catch(Throwableex){if(exinstanceofBeanCreationException&&beanName.equals(((BeanCreationException)ex).getBeanName())){throw(BeanCreationException)ex;}else{thrownewBeanCreationException(mbd.getResourceDescription(),beanName,"Initializationofbeanfailed",ex);}}/**省略代码**/

在生命周期中 populateBean 进行填充bean数据。把其他依赖引入进来

BeanPostProcessor 是一个bean创建时候的一个钩子。

以下代码 是循环调用实现了 BeanPostProcessor 子类 InstantiationAwareBeanPostProcessor#postProcessProperties 方法

Spring 在以下代码中有自动注入的拓展点。 关键就是实现 InstantiationAwareBeanPostProcessor#postProcessProperties

/**省略代码**/for(BeanPostProcessorbp:getBeanPostProcessors()){if(bpinstanceofInstantiationAwareBeanPostProcessor){InstantiationAwareBeanPostProcessoribp=(InstantiationAwareBeanPostProcessor)bp;//对所有需要依赖检查的属性进行后处理PropertyValuespvsToUse=ibp.postProcessProperties(pvs,bw.getWrappedInstance(),beanName);if(pvsToUse==null){//从bw对象中提取PropertyDescriptor结果集//PropertyDescriptor:可以通过一对存取方法提取一个属性if(filteredPds==null){filteredPds=filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching);}pvsToUse=ibp.postProcessPropertyValues(pvs,filteredPds,bw.getWrappedInstance(),beanName);if(pvsToUse==null){return;}}pvs=pvsToUse;}}/**省略代码**/

我们展开来讲一下 @Autowired 的实现是怎么样的吧:

实现类为 AutowiredAnnotationBeanPostProcessor.java

从上面可以得知,填充bean的时候。时调用了方法 ibp.postProcessPropertyValues()

那么 AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues() 则会被调用

调用 findAutowiringMetadata 获取 class 以及父类 带有 @Autowired 或者 @Value 的属性或者方法:

/**省略代码**/publicPropertyValuespostProcessProperties(PropertyValuespvs,Objectbean,StringbeanName){//获取所有可以注入的元数据InjectionMetadatametadata=findAutowiringMetadata(beanName,bean.getClass(),pvs);try{//注入数据metadata.inject(bean,beanName,pvs);}catch(BeanCreationExceptionex){throwex;}catch(Throwableex){thrownewBeanCreationException(beanName,"Injectionofautowireddependenciesfailed",ex);}returnpvs;}privateInjectionMetadatafindAutowiringMetadata(StringbeanName,Class<?>clazz,@NullablePropertyValuespvs){//缓存名字获取StringcacheKey=(StringUtils.hasLength(beanName)?beanName:clazz.getName());InjectionMetadatametadata=this.injectionMetadataCache.get(cacheKey);//获取是否已经读取过这个class类的InjectionMetadata有的话直接从缓存中获取出去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);}}}returnmetadata;}privateInjectionMetadatabuildAutowiringMetadata(finalClass<?>clazz){if(!AnnotationUtils.isCandidateClass(clazz,this.autowiredAnnotationTypes)){returnInjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement>elements=newArrayList<>();Class<?>targetClass=clazz;do{finalList<InjectionMetadata.InjectedElement>currElements=newArrayList<>();//循环targetClass的所有field并执FieldCallback逻辑(函数式编程接口,传入的是一个执行函数)ReflectionUtils.doWithLocalFields(targetClass,field->{//获得字段上面的Annotation注解MergedAnnotation<?>ann=findAutowiredAnnotation(field);if(ann!=null){//判断是否为静态属性如果是,则不进行注入if(Modifier.isStatic(field.getModifiers())){if(logger.isInfoEnabled()){logger.info("Autowiredannotationisnotsupportedonstaticfields:"+field);}return;}//注解是否为必须依赖项booleanrequired=determineRequiredStatus(ann);currElements.add(newAutowiredFieldElement(field,required));}});//循环targetClass的所有Method并执MethodCallback逻辑(函数式编程接口,传入的是一个执行函数)ReflectionUtils.doWithLocalMethods(targetClass,method->{MethodbridgedMethod=BridgeMethodResolver.findBridgedMethod(method);if(!BridgeMethodResolver.isVisibilityBridgeMethodPair(method,bridgedMethod)){return;}MergedAnnotation<?>ann=findAutowiredAnnotation(bridgedMethod);if(ann!=null&&method.equals(ClassUtils.getMostSpecificMethod(method,clazz))){//判断是否为静态方法如果是,则不进行注入if(Modifier.isStatic(method.getModifiers())){if(logger.isInfoEnabled()){logger.info("Autowiredannotationisnotsupportedonstaticmethods:"+method);}return;}//判断静态方法参数是否为0if(method.getParameterCount()==0){if(logger.isInfoEnabled()){logger.info("Autowiredannotationshouldonlybeusedonmethodswithparameters:"+method);}}booleanrequired=determineRequiredStatus(ann);PropertyDescriptorpd=BeanUtils.findPropertyForMethod(bridgedMethod,clazz);currElements.add(newAutowiredMethodElement(method,required,pd));}});//数据加到数组最前方父类的的注解都放在靠前的位置elements.addAll(0,currElements);//如果有父类则设置targetClass为父类。如此循环targetClass=targetClass.getSuperclass();}while(targetClass!=null&&targetClass!=Object.class);returnInjectionMetadata.forElements(elements,clazz);}/**省略代码**/

真正注入数据的是 metadata.inject(bean, beanName, pvs);

调用的是 InjectionMetadata#inject 方法

publicvoidinject(Objecttarget,@NullableStringbeanName,@NullablePropertyValuespvs)throwsThrowable{Collection<InjectedElement>checkedElements=this.checkedElements;//带有注解的方法或者属性列表Collection<InjectedElement>elementsToIterate=(checkedElements!=null?checkedElements:this.injectedElements);if(!elementsToIterate.isEmpty()){for(InjectedElementelement:elementsToIterate){element.inject(target,beanName,pvs);}}}

循环调用之前加入的带有注解的方法或者属性构建的对象 AutowiredFieldElement#injectAutowiredMethodElement#inject

/***属性上有注解构建的处理对象*/privateclassAutowiredFieldElementextendsInjectionMetadata.InjectedElement{privatefinalbooleanrequired;privatevolatilebooleancached;@NullableprivatevolatileObjectcachedFieldValue;publicAutowiredFieldElement(Fieldfield,booleanrequired){super(field,null);this.required=required;}@Overrideprotectedvoidinject(Objectbean,@NullableStringbeanName,@NullablePropertyValuespvs)throwsThrowable{//获取属性名Fieldfield=(Field)this.member;Objectvalue;//Bean不是单例的话,会重复进入注入的这个操作,if(this.cached){try{value=resolvedCachedArgument(beanName,this.cachedFieldValue);}catch(NoSuchBeanDefinitionExceptionex){//Unexpectedremovaloftargetbeanforcachedargument->re-resolvevalue=resolveFieldValue(field,bean,beanName);}}else{//首次创建的时候进入该方法value=resolveFieldValue(field,bean,beanName);}if(value!=null){//属性如果不为public的话,则设置为可访问ReflectionUtils.makeAccessible(field);field.set(bean,value);}}@NullableprivateObjectresolveFieldValue(Fieldfield,Objectbean,@NullableStringbeanName){//构建DependencyDescriptor对象DependencyDescriptordesc=newDependencyDescriptor(field,this.required);desc.setContainingClass(bean.getClass());//注入bean的数量。有可能字段上是一个ListSet<String>autowiredBeanNames=newLinkedHashSet<>(1);Assert.state(beanFactory!=null,"NoBeanFactoryavailable");//获得beanFactory类型转换类TypeConvertertypeConverter=beanFactory.getTypeConverter();Objectvalue;try{//查找依赖关系value=beanFactory.resolveDependency(desc,beanName,autowiredBeanNames,typeConverter);}catch(BeansExceptionex){thrownewUnsatisfiedDependencyException(null,beanName,newInjectionPoint(field),ex);}synchronized(this){if(!this.cached){ObjectcachedFieldValue=null;if(value!=null||this.required){cachedFieldValue=desc;//填入依赖关系registerDependentBeans(beanName,autowiredBeanNames);//判断如果注入依赖是只有一个if(autowiredBeanNames.size()==1){StringautowiredBeanName=autowiredBeanNames.iterator().next();if(beanFactory.containsBean(autowiredBeanName)&&beanFactory.isTypeMatch(autowiredBeanName,field.getType())){cachedFieldValue=newShortcutDependencyDescriptor(desc,autowiredBeanName,field.getType());}}}this.cachedFieldValue=cachedFieldValue;this.cached=true;}}returnvalue;}}/***方法上有注解构建的处理对象*/privateclassAutowiredMethodElementextendsInjectionMetadata.InjectedElement{privatefinalbooleanrequired;privatevolatilebooleancached;@NullableprivatevolatileObject[]cachedMethodArguments;publicAutowiredMethodElement(Methodmethod,booleanrequired,@NullablePropertyDescriptorpd){super(method,pd);this.required=required;}@Overrideprotectedvoidinject(Objectbean,@NullableStringbeanName,@NullablePropertyValuespvs)throwsThrowable{//检查属性是不会在之前就已经注入过了。如果主如果则不进行二次覆盖if(checkPropertySkipping(pvs)){return;}Methodmethod=(Method)this.member;Object[]arguments;if(this.cached){try{arguments=resolveCachedArguments(beanName);}catch(NoSuchBeanDefinitionExceptionex){//Unexpectedremovaloftargetbeanforcachedargument->re-resolvearguments=resolveMethodArguments(method,bean,beanName);}}else{//首次创建的时候进入该方法arguments=resolveMethodArguments(method,bean,beanName);}if(arguments!=null){try{//属性如果不为public的话,则设置为可访问ReflectionUtils.makeAccessible(method);//调用方法并传入参数method.invoke(bean,arguments);}catch(InvocationTargetExceptionex){throwex.getTargetException();}}}@NullableprivateObject[]resolveCachedArguments(@NullableStringbeanName){Object[]cachedMethodArguments=this.cachedMethodArguments;if(cachedMethodArguments==null){returnnull;}Object[]arguments=newObject[cachedMethodArguments.length];for(inti=0;i<arguments.length;i++){arguments[i]=resolvedCachedArgument(beanName,cachedMethodArguments[i]);}returnarguments;}@NullableprivateObject[]resolveMethodArguments(Methodmethod,Objectbean,@NullableStringbeanName){//获取方法上有几个参数intargumentCount=method.getParameterCount();Object[]arguments=newObject[argumentCount];DependencyDescriptor[]descriptors=newDependencyDescriptor[argumentCount];Set<String>autowiredBeans=newLinkedHashSet<>(argumentCount);Assert.state(beanFactory!=null,"NoBeanFactoryavailable");TypeConvertertypeConverter=beanFactory.getTypeConverter();for(inti=0;i<arguments.length;i++){//方法参数,从方法参数中取出i构造MethodParameter对象MethodParametermethodParam=newMethodParameter(method,i);DependencyDescriptorcurrDesc=newDependencyDescriptor(methodParam,this.required);currDesc.setContainingClass(bean.getClass());descriptors[i]=currDesc;try{//获取方法中i参数的内容Objectarg=beanFactory.resolveDependency(currDesc,beanName,autowiredBeans,typeConverter);if(arg==null&&!this.required){arguments=null;break;}arguments[i]=arg;}catch(BeansExceptionex){thrownewUnsatisfiedDependencyException(null,beanName,newInjectionPoint(methodParam),ex);}}synchronized(this){if(!this.cached){if(arguments!=null){DependencyDescriptor[]cachedMethodArguments=Arrays.copyOf(descriptors,arguments.length);registerDependentBeans(beanName,autowiredBeans);if(autowiredBeans.size()==argumentCount){Iterator<String>it=autowiredBeans.iterator();Class<?>[]paramTypes=method.getParameterTypes();for(inti=0;i<paramTypes.length;i++){StringautowiredBeanName=it.next();if(beanFactory.containsBean(autowiredBeanName)&&beanFactory.isTypeMatch(autowiredBeanName,paramTypes[i])){cachedMethodArguments[i]=newShortcutDependencyDescriptor(descriptors[i],autowiredBeanName,paramTypes[i]);}}}this.cachedMethodArguments=cachedMethodArguments;}else{this.cachedMethodArguments=null;}this.cached=true;}}returnarguments;}}

以上就是 @Autowired 实现的完整流程。 可概括为: populateBean -> AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues -> 获取带有注解的属性和方法构建 AutowiredFieldElementAutowiredMethodElement 对象,然后循环调用了 inject 进行属性调用

自定义自动注入注解。

编写抽象类代码:

packagecom.yunlongn.common.core.autowired;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.springframework.beans.BeansException;importorg.springframework.beans.PropertyValues;importorg.springframework.beans.factory.*;importorg.springframework.beans.factory.annotation.InjectionMetadata;importorg.springframework.beans.factory.config.ConfigurableListableBeanFactory;importorg.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;importorg.springframework.core.annotation.AnnotationUtils;importorg.springframework.core.annotation.MergedAnnotation;importorg.springframework.core.annotation.MergedAnnotations;importorg.springframework.lang.Nullable;importorg.springframework.util.ReflectionUtils;importorg.springframework.util.StringUtils;importjava.beans.PropertyDescriptor;importjava.lang.annotation.Annotation;importjava.lang.reflect.*;importjava.util.*;importjava.util.concurrent.ConcurrentHashMap;/***抽象的自动注入方法*@authoryunlgongn*/publicabstractclassAbstractAnnotationBeanPostProcessorimplementsInstantiationAwareBeanPostProcessor{privatefinalSet<Class<?extendsAnnotation>>annotationTypes=newLinkedHashSet<>(4);privatefinalMap<String,InjectionMetadata>injectionMetadataCache=newConcurrentHashMap<>(256);protectedfinalLoglogger=LogFactory.getLog(getClass());/***处理的annotationType对象*@returnAnnotation自定义注解*/publicabstractClass<?extendsAnnotation>annotationType();AbstractAnnotationBeanPostProcessor(){Class<?extendsAnnotation>annotation=this.annotationType();annotationTypes.add(annotation);}@OverridepublicObjectpostProcessBeforeInstantiation(Class<?>beanClass,StringbeanName)throwsBeansException{returnInstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass,beanName);}@OverridepublicbooleanpostProcessAfterInstantiation(Objectbean,StringbeanName)throwsBeansException{returnInstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean,beanName);}@OverridepublicPropertyValuespostProcessProperties(PropertyValuespvs,Objectbean,StringbeanName){InjectionMetadatametadata=findAbstractMetadata(beanName,bean.getClass(),pvs);try{//注入数据metadata.inject(bean,beanName,pvs);}catch(BeanCreationExceptionex){throwex;}catch(Throwableex){thrownewBeanCreationException(beanName,"Injectionofautowireddependenciesfailed",ex);}returnpvs;}privateInjectionMetadatafindAbstractMetadata(StringbeanName,Class<?>clazz,@NullablePropertyValuespvs){StringcacheKey=(StringUtils.hasLength(beanName)?beanName:clazz.getName());InjectionMetadatametadata=this.injectionMetadataCache.get(cacheKey);//获取是否已经读取过这个class类的InjectionMetadata有的话直接从缓存中获取出去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=buildAbstractMetadata(clazz);this.injectionMetadataCache.put(cacheKey,metadata);}}}returnmetadata;}privateInjectionMetadatabuildAbstractMetadata(finalClass<?>clazz){if(!AnnotationUtils.isCandidateClass(clazz,this.annotationTypes)){returnInjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement>elements=newArrayList<>();Class<?>targetClass=clazz;do{finalList<InjectionMetadata.InjectedElement>currElements=newArrayList<>();//循环targetClass的所有field并执FieldCallback逻辑(函数式编程接口,传入的是一个执行函数)ReflectionUtils.doWithLocalFields(targetClass,field->{//获得字段上面的Annotation注解MergedAnnotation<?>ann=findAbstractAnnotation(field);if(ann!=null){//判断是否为静态属性如果是,则不进行注入if(Modifier.isStatic(field.getModifiers())){if(logger.isInfoEnabled()){logger.info("Abstractannotationisnotsupportedonstaticfields:"+field);}return;}currElements.add(newAbstractFieldElement(field,ann));}});//数据加到数组最前方父类的的注解都放在靠前的位置elements.addAll(0,currElements);targetClass=targetClass.getSuperclass();}while(targetClass!=null&&targetClass!=Object.class);returnInjectionMetadata.forElements(elements,clazz);}@NullableprivateMergedAnnotation<?>findAbstractAnnotation(AccessibleObjectao){//将指定方法上的注解合并成一个注解MergedAnnotationsannotations=MergedAnnotations.from(ao);//循环要扫描的注解annotationTypes那个在前面就认哪个for(Class<?extendsAnnotation>type:this.annotationTypes){MergedAnnotation<?>annotation=annotations.get(type);if(annotation.isPresent()){returnannotation;}}returnnull;}@Deprecated@OverridepublicPropertyValuespostProcessPropertyValues(PropertyValuespvs,PropertyDescriptor[]pds,Objectbean,StringbeanName){returnpostProcessProperties(pvs,bean,beanName);}@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{returnInstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean,beanName);}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{returnInstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean,beanName);}/***实现交给子类进行实现将注解透传出去*@parammergedAnnotation属性上的注解*@parambeanbean实例*@parambeanNamebean的名字*@paramfield字段*@paramautowiredFieldElement注解*@return注入对象*@throwsException*/protectedabstractObjectgetInjectedObject(MergedAnnotation<?>mergedAnnotation,Objectbean,StringbeanName,Fieldfield,AbstractFieldElementautowiredFieldElement)throwsException;publicclassAbstractFieldElementextendsInjectionMetadata.InjectedElement{privatefinalMergedAnnotation<?>mergedAnnotation;publicAbstractFieldElement(Fieldfield,MergedAnnotation<?>mergedAnnotation){super(field,null);this.mergedAnnotation=mergedAnnotation;}@Overrideprotectedvoidinject(Objectbean,@NullableStringbeanName,@NullablePropertyValuespvs)throwsThrowable{Fieldfield=(Field)this.member;Objectvalue=getInjectedObject(this.mergedAnnotation,bean,beanName,field,this);if(value!=null){ReflectionUtils.makeAccessible(field);field.set(bean,value);}}}}

抽象类实现,实现一个 @RedisAutowired 自定义注入注解

packagecom.yunlongn.common.core.autowired;importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.BeanFactory;importorg.springframework.beans.factory.BeanFactoryAware;importorg.springframework.core.annotation.MergedAnnotation;importjava.lang.annotation.Annotation;importjava.lang.reflect.Field;publicclassRedisAutowiredBeanPostProcessorextendsAbstractAnnotationBeanPostProcessorimplementsBeanFactoryAware{privateBeanFactorybeanFactory=null;@OverridepublicClass<?extendsAnnotation>annotationType(){returnRedisAutowired.class;}@OverrideprotectedObjectgetInjectedObject(MergedAnnotation<?>mergedAnnotation,Objectbean,StringbeanName,Fieldfield,AbstractAnnotationBeanPostProcessor.AbstractFieldElementautowiredFieldElement)throwsException{//从value中获取bean的名字。或者通过一些其他的逻辑获取名字Strings=mergedAnnotation.getString("value");returnbeanFactory.getBean(s);}@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{this.beanFactory=beanFactory;}}

在 Application 引入以上 @Import(RedisAutowiredBeanPostProcessor.class) 那么 @RedisAutowired 注解就生效了

@RedisAutowired("db102")privateXXXServiceservice;

使用注解如上

作者:云扬四海


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Spring/302.html