@Autowired寻找注入点
本文源码基于spring-framework-5.3.10。 在属性注入的时候,spring需要找到那些属性需要注入! 源码位于:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(RootBeanDefinition, Class<?>, String) 他在Bean的生命周期的合并BeanDefinition中调用。
@Autowired注解可以写的位置
属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个 set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
@Autowired寻找注入点原理
遍历当前类的所有的属性字段Field 查看字段上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该字段是一个注入点 如果字段是static的,则不进行注入 获取@Autowired中的required属性的值 将字段信息构造成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中。 遍历当前类的所有方法Method 判断当前Method是否是桥接方法,如果是找到原方法 查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法是一个注入点 如果方法是static的,则不进行注入 获取@Autowired中的required属性的值 将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到currElements集合中。 遍历完当前类的字段和方法后,将遍历父类的,直到没有父类。 最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并缓存。
@Autowired寻找注入点:postProcessMergedBeanDefinition源码分析
@Override
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 ( ) ) ;
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;
}
private InjectionMetadata buildAutowiringMetadata ( final Class < ? > clazz) {
if ( ! AnnotationUtils . isCandidateClass ( clazz, this . autowiredAnnotationTypes) ) {
return InjectionMetadata . EMPTY;
}
List < InjectionMetadata. InjectedElement > elements = new ArrayList < > ( ) ;
Class < ? > targetClass = clazz;
do {
final List < InjectionMetadata. InjectedElement > currElements = new ArrayList < > ( ) ;
ReflectionUtils . doWithLocalFields ( targetClass, field -> {
MergedAnnotation < ? > ann = findAutowiredAnnotation ( field) ;
if ( ann != null ) {
if ( Modifier . isStatic ( field. getModifiers ( ) ) ) {
if ( logger. isInfoEnabled ( ) ) {
logger. info ( "Autowired annotation is not supported on static fields: " + field) ;
}
return ;
}
boolean required = determineRequiredStatus ( ann) ;
currElements. add ( new AutowiredFieldElement ( field, required) ) ;
}
} ) ;
ReflectionUtils . doWithLocalMethods ( targetClass, method -> {
Method bridgedMethod = 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 ( "Autowired annotation is not supported on static methods: " + method) ;
}
return ;
}
if ( method. getParameterCount ( ) == 0 ) {
if ( logger. isInfoEnabled ( ) ) {
logger. info ( "Autowired annotation should only be used on methods with parameters: " +
method) ;
}
}
boolean required = determineRequiredStatus ( ann) ;
PropertyDescriptor pd = BeanUtils . findPropertyForMethod ( bridgedMethod, clazz) ;
currElements. add ( new AutowiredMethodElement ( method, required, pd) ) ;
}
} ) ;
elements. addAll ( 0 , currElements) ;
targetClass = targetClass. getSuperclass ( ) ;
}
while ( targetClass != null && targetClass != Object . class ) ;
return InjectionMetadata . forElements ( elements, clazz) ;
}
一个字段能不能成为注入点
private MergedAnnotation < ? > findAutowiredAnnotation ( AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations . from ( ao) ;
for ( Class < ? extends Annotation > type : this . autowiredAnnotationTypes) {
MergedAnnotation < ? > annotation = annotations. get ( type) ;
if ( annotation. isPresent ( ) ) {
return annotation;
}
}
return null ;
}
有什么样的标记会成为注入点?
public AutowiredAnnotationBeanPostProcessor ( ) {
this . autowiredAnnotationTypes. add ( Autowired . class ) ;
this . autowiredAnnotationTypes. add ( Value . class ) ;
try {
this . autowiredAnnotationTypes. add ( ( Class < ? extends Annotation > )
ClassUtils . forName ( "javax.inject.Inject" , AutowiredAnnotationBeanPostProcessor . class . getClassLoader ( ) ) ) ;
logger. trace ( "JSR-330 'javax.inject.Inject' annotation found and supported for autowiring" ) ;
}
catch ( ClassNotFoundException ex) {
}
}
结束语
获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师! 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解! 关注公众号,后续持续高效的学习JVM! 这个公众号,无广告!!!每日更新!!!