zoukankan      html  css  js  c++  java
  • Spring IOC:BeanDefinition加载注册流程(转)

    BeanFactory接口体系

    以DefaultListableBeanFactory为例梳理一下BeanFactory接口体系的细节

    img

    主要接口、抽象类的作用如下:

    1. BeanFactory(根据注册的bean定义来生产bean的功能)

    2. BeanRegistry(bean定义的注册功能)

    3. BeanDefinition(bean的定义信息)

    BeanFactory

    1. BeanFactory:用于访问Spring bean容器的根接口,提供多个重载的getBean方法来获取注册到容器中的bean的实例

    2. HierarchicalBeanFactory:为Spring bean 容器提供父子容器的上下层级关系的能力

    3. ListableBeanFactory:提供遍历Spring bean容器中bean的能力但其方法只检查容器内部bean的定义,而不会真正的实例化bean;并且不会包含其父容器中的bean定义

    4. ConfigurableBeanFactory:提供遍历Spring bean容器的能力,比如向container中增加BeanPostProcessor

    5. AutowireCapableBeanFactory:提供自动注入bean属性的能力,以及其他框架的集成代码可以利用这个接口来连接和填充Spring无法控制的现有bean实例生命周期

    BeanRegistry

    1. AliasRegistry:用于管理bean别名的接口

    2. BeanDefinitionRegistry:提供注册BeanDefinition的能力

    BeanRegistry

    1. AliasRegistry:用于管理bean别名的接口

    2. BeanDefinitionRegistry:提供注册BeanDefinition的能力

    BeanDefinition

    1. AnnotatedBeanDefinition:注解的元数据

    2. RootBeanDefinition:在Spring bean容器运行期间,通过合并注册到容器中的bean定义生成的bean元数据

    总结

    在spring的容器接口体系中,我们可以使用原材料、工厂、生产线操作工人、最终产品的关系来类比BeanDefinition、BeanFactory、BeanRegistry、bean实例。 BeanRegistry提供能力将BeanDefinition注册到BeanFactory中,BeanFactory通过其内部的生产线来生成bean实例

     

    BeanDefinition的接口实现类体系

    以AnnotatedGenericBeanDefinition为例梳理一下BeanDefinition接口实现类体系

    Metadata元数据部分

    Metadata元数据部分在其内部包装了需要注册到BeanFactory的类的信息

    类图

    img

    类关系说明

    1. ClassMetadata,抽象出类的元数据的接口。提供获取类名、判断是否为接口类、是否为注解类、是否为抽象类等功能;

    2. AnnotatedTypeMetadata,定义了接口,用于访问AnnotationMetadata、MethodMetadata这两个类的注解。提供判断是否被指定注解标记、获取指定注解的属性等功能;

    3. AnnotationMetadata,定义了接口,用于访问指定类的注解;如getMetaAnnotationTypes(String annotationName)用于获取指定注解annotationName的元注解集合

    4. StandardClassMetadata,用标准的反射功能实现了ClassMetadata类

    5. StandardAnnotationMetadata,扩展StandardClassMetadata类并实现AnnotationMetadata接口

    BeanDefinition部分

    BeanDefinition作为注册到BeanFactory中的载体,在具体的实现类中,持有metadata实例。

    类图

    img

    类关系说明

    1. AttributeAccessor,定义设置和获取属性元数据的接口;

    2. AttributeAccessorSupport,在内部通过LinkedHashMap实现了AttributeAccessor接口;

    3. BeanMetadataElement,持有一个source,具体用途待考究;

    4. BeanMetadataAttribute,实现BeanMetadataElement接口,在其内部以key-value的形式持有bean definition的属性;

    5. BeanMetadataAttributeAccessor,实现BeanMetadataElement接口,并重写部分AttributeAccessorSupport的接口,用于设置和获取BeanMetadataElement;

    6. BeanDefinition,一个BeanDefinition对象用于描述一个bean instance,其中拥有属性值、构造器属性值以及更多由其子类提供的信息;

    7. AbstractBeanDefinition:实现了BeanDefinition接口,提供了设置和获取bean definition中的各个属性(即类的各种属性数据)

    8. AnnotatedBeanDefinition,提供接口用于获取被包装的类的元数据

    9. GenericBeanDefinition,提供parent bean的设置功能

    10. AnnotatedGenericBeanDefinition,扩展自GenericBeanDefinition,实现AnnotatedBeanDefinition提供暴露注解元数据的支持功能

     

    注册注解配置类流程

    主流程

     

    img

    源码分析

     1 public class AnnotatedBeanDefinitionReader {
     2  3     // 省略部分代码
     4     public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
     5         AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
     6         if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
     7             return;
     8         }
     9         // 解析@Scope注解,获取bean的作用域配置信息
    10         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    11         abd.setScope(scopeMetadata.getScopeName());
    12         String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    13         // 解析通用注解,如@Lazy等
    14         AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    15         // 定义qualifier信息,主要涉及到后续指定bean注入的注解@Qualifier
    16         if (qualifiers != null) {
    17             for (Class<? extends Annotation> qualifier : qualifiers) {
    18                 if (Primary.class == qualifier) {
    19                     abd.setPrimary(true);
    20                 }
    21                 else if (Lazy.class == qualifier) {
    22                     abd.setLazyInit(true);
    23                 }
    24                 else {
    25                     abd.addQualifier(new AutowireCandidateQualifier(qualifier));
    26                 }
    27             }
    28         }
    29 30         BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    31         // 根据ScopeMetadata生成对应的Scope代理
    32         definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    33         // 实际bean的注入,在registry内部用一个ConcurrentHashMap持有了beandefinition信息
    34         BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    35     }
    36 37 }

    解析@Scope的流程,分析spring解析注解类属性值的流程

    主流程

     

    img

     

    源码分析

      1 // @Scope注解的解析器
      2 public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
      3   4     // 解析@Scope注解,构造ScopeMetadata实例,持有bean作用域的配置信息
      5     @Override
      6     public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
      7         ScopeMetadata metadata = new ScopeMetadata();
      8         if (definition instanceof AnnotatedBeanDefinition) {
      9             AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
     10             // 获取指定注解的属性值对,此处为@Scope注解
     11             AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
     12                     annDef.getMetadata(), this.scopeAnnotationType);
     13             // 如果属性不为null,则根据属性值对修改ScopeMetadata的值
     14             if (attributes != null) {
     15                 metadata.setScopeName(attributes.getString("value"));
     16                 ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
     17                 if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
     18                     proxyMode = this.defaultProxyMode;
     19                 }
     20                 metadata.setScopedProxyMode(proxyMode);
     21             }
     22         }
     23         return metadata;
     24     }
     25  26 }
     27  28 // 注解配置信息的辅助工具类
     29 public class AnnotationConfigUtils {
     30  31     // 获取metadata中,annotationClass注解类型的属性值,用AnnotationAttributes(继承自LinkedHashMap,额外保存了注解类型等信息)持有
     32     static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
     33         return attributesFor(metadata, annotationClass.getName());
     34     }
     35  36     // 获取metadata中,annotationClass注解类型的属性值,用AnnotationAttributes(继承自LinkedHashMap,额外保存了注解类型等信息)持有
     37     static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
     38         return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
     39     }
     40  41 }
     42  43 // 持有类的元数据
     44 public class StandardAnnotationMetadata extends StandardClassMetadata implements AnnotationMetadata {
     45  46     // 获取指定注解名annotationName中的属性值对
     47     @Override
     48     public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
     49         return (this.annotations.length > 0 ? AnnotatedElementUtils.getMergedAnnotationAttributes(
     50                 getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap) : null);
     51     }
     52  53 }
     54  55 // 用于在AnnotatedElement上查找注解、元注解、可重复注解的工具类
     56 public class AnnotatedElementUtils {
     57  58     public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
     59             String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
     60  61         Assert.hasLength(annotationName, "'annotationName' must not be null or empty");
     62         // 根据注解名查找注解的属性值对
     63         AnnotationAttributes attributes = searchWithGetSemantics(element, null, annotationName,
     64                 new MergedAnnotationAttributesProcessor(classValuesAsString, nestedAnnotationsAsMap));
     65  66         // 处理注解别名
     67         AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
     68         return attributes;
     69     }
     70  71     private static <T> T searchWithGetSemantics(AnnotatedElement element,
     72             Class<? extends Annotation> annotationType, String annotationName, Processor<T> processor) {
     73         // 将查找工作,转发给processor处理(Processor -> MergedAnnotationAttributesProcessor)
     74         return searchWithGetSemantics(element, annotationType, annotationName, null, processor);
     75     }
     76  77     private static <T> T searchWithGetSemantics(AnnotatedElement element,
     78             Class<? extends Annotation> annotationType, String annotationName,
     79             Class<? extends Annotation> containerType, Processor<T> processor) {
     80  81         try {
     82             // 进行第一层查找(metaDepth=0)
     83             return searchWithGetSemantics(element, annotationType, annotationName,
     84                     containerType, processor, new HashSet<AnnotatedElement>(), 0);
     85         }
     86         catch (Throwable ex) {
     87             AnnotationUtils.rethrowAnnotationConfigurationException(ex);
     88             throw new IllegalStateException("Failed to introspect annotations on " + element, ex);
     89         }
     90     }
     91  92     private static <T> T searchWithGetSemantics(AnnotatedElement element,
     93             Class<? extends Annotation> annotationType, String annotationName,
     94             Class<? extends Annotation> containerType, Processor<T> processor,
     95             Set<AnnotatedElement> visited, int metaDepth) {
     96  97         Assert.notNull(element, "AnnotatedElement must not be null");
     98  99         if (visited.add(element)) {
    100             try {
    101                 // Start searching within locally declared annotations
    102                 List<Annotation> declaredAnnotations = Arrays.asList(element.getDeclaredAnnotations());
    103                 // 转发给重载方法,进行实际的查找操作
    104                 T result = searchWithGetSemanticsInAnnotations(element, declaredAnnotations,
    105                         annotationType, annotationName, containerType, processor, visited, metaDepth);
    106                 if (result != null) {
    107                     return result;
    108                 }
    109 110                 if (element instanceof Class) {  // otherwise getAnnotations does not return anything new
    111                     List<Annotation> inheritedAnnotations = new ArrayList<Annotation>();
    112                     for (Annotation annotation : element.getAnnotations()) {
    113                         if (!declaredAnnotations.contains(annotation)) {
    114                             inheritedAnnotations.add(annotation);
    115                         }
    116                     }
    117 118                     // Continue searching within inherited annotations
    119                     result = searchWithGetSemanticsInAnnotations(element, inheritedAnnotations,
    120                             annotationType, annotationName, containerType, processor, visited, metaDepth);
    121                     if (result != null) {
    122                         return result;
    123                     }
    124                 }
    125             }
    126             catch (Throwable ex) {
    127                 AnnotationUtils.handleIntrospectionFailure(element, ex);
    128             }
    129         }
    130 131         return null;
    132     }
    133 134     // 执行实际的注解属性查找功能
    135     private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement element,
    136             List<Annotation> annotations, Class<? extends Annotation> annotationType,
    137             String annotationName, Class<? extends Annotation> containerType,
    138             Processor<T> processor, Set<AnnotatedElement> visited, int metaDepth) {
    139 140         // Search in annotations
    141         // 遍历注解列表
    142         for (Annotation annotation : annotations) {
    143             Class<? extends Annotation> currentAnnotationType = annotation.annotationType();
    144             // 只处理非JDK内置的注解
    145             if (!AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
    146                 // 满足以下任意条件,需要调用processor.process(element, annotation, metaDepth)方法进行属性值的查找工作
    147                 // 1. 如果当前循环的注解,为我们指定的注解类型
    148                 // 2. 如果当前循环的注解,为我们指定的注解名称
    149                 // 3. 始终调用processor,即processor.alwaysProcesses()返回true
    150                 if (currentAnnotationType == annotationType ||
    151                         currentAnnotationType.getName().equals(annotationName) ||
    152                         processor.alwaysProcesses()) {
    153                     // 查找注解属性值
    154                     T result = processor.process(element, annotation, metaDepth);
    155                     if (result != null) {
    156                         
    157                         if (processor.aggregates() && metaDepth == 0) {
    158                             // 聚合查找结果
    159                             processor.getAggregatedResults().add(result);
    160                         }
    161                     else {
    162     return result;
    163     }
    164     }
    165     }
    166     // Repeatable annotations in container?
    167     else if (currentAnnotationType == containerType) {
    168     for (Annotation contained : getRawAnnotationsFromContainer(element, annotation)) {
    169     T result = processor.process(element, contained, metaDepth);
    170     if (result != null) {
    171     // No need to post-process since repeatable annotations within a
    172     // container cannot be composed annotations.
    173     processor.getAggregatedResults().add(result);
    174     }
    175     }
    176     }
    177     }
    178     }
    179 180     // Recursively search in meta-annotations
    181     for (Annotation annotation : annotations) {
    182     Class<? extends Annotation> currentAnnotationType = annotation.annotationType();
    183     if (!AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
    184     T result = searchWithGetSemantics(currentAnnotationType, annotationType,
    185     annotationName, containerType, processor, visited, metaDepth + 1);
    186     if (result != null) {
    187     processor.postProcess(element, annotation, result);
    188     if (processor.aggregates() && metaDepth == 0) {
    189     processor.getAggregatedResults().add(result);
    190     }
    191     else {
    192     return result;
    193     }
    194     }
    195     }
    196     }
    197 198     return null;
    199     }
    200 201 }
    202 203 private static class MergedAnnotationAttributesProcessor implements Processor<AnnotationAttributes> {
    204 205     @Override
    206     public AnnotationAttributes process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {
    207         return AnnotationUtils.retrieveAnnotationAttributes(annotatedElement, annotation,
    208                 this.classValuesAsString, this.nestedAnnotationsAsMap);
    209     }
    210 211 }
    212 213 214 public abstract class AnnotationUtils {
    215 216     // 将注解属性值包装为AnnotationAttributes,返回给上层调用
    217     static AnnotationAttributes retrieveAnnotationAttributes(Object annotatedElement, Annotation annotation,
    218     boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
    219 220     Class<? extends Annotation> annotationType = annotation.annotationType();
    221     AnnotationAttributes attributes = new AnnotationAttributes(annotationType);
    222 223     for (Method method : getAttributeMethods(annotationType)) {
    224     try {
    225       Object attributeValue = method.invoke(annotation);
    226       Object defaultValue = method.getDefaultValue();
    227       if (defaultValue != null && ObjectUtils.nullSafeEquals(attributeValue, defaultValue)) {
    228         attributeValue = new DefaultValueHolder(defaultValue);
    229       }
    230       attributes.put(method.getName(),
    231       adaptValue(annotatedElement, attributeValue, classValuesAsString, nestedAnnotationsAsMap));
    232     }
    233     catch (Throwable ex) {
    234         if (ex instanceof InvocationTargetException) {
    235           Throwable targetException = ((InvocationTargetException) ex).getTargetException();
    236           rethrowAnnotationConfigurationException(targetException);
    237         }
    238         throw new IllegalStateException("Could not obtain annotation attribute value for " + method, ex);
    239       }
    240     }
    241 242     return attributes;
    243     }
    244 245 }

    基于注解配置,注册bean的原理

    在spring的高版本中,官方建议开发者使用java code的配置方式。其原理主要是利用ConfigurationClassPostProcessor类来进行解析。执行的时机发生在容器启动后,调用invokeBeanFactoryPostProcessors()方法这一步。

    主流程

    img

    源码分析

      1 public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
      2         PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
      3   4     public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
      5         List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
      6         String[] candidateNames = registry.getBeanDefinitionNames();
      7   8         // 遍历beanfactory中所有已注册的bean
      9         for (String beanName : candidateNames) {
     10             BeanDefinition beanDef = registry.getBeanDefinition(beanName);
     11             // 判断是否为处理过的full配置类
     12             if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
     13                     // 判断是否为处理过的lite配置类
     14                     ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
     15                 if (logger.isDebugEnabled()) {
     16                     logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
     17                 }
     18             }
     19             // 判断是否为配置类(标注了@Configuration、@Component、@ComponentScan、@Import、@ImportResource)
     20             // 为full配置类时,为beanDef增加键为org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass,值为full的attribute
     21             // 为lite配置类时,为beanDef增加键为org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass,值为lite的attribute
     22             else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
     23                 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
     24             }
     25         }
     26  27         // Return immediately if no @Configuration classes were found
     28         if (configCandidates.isEmpty()) {
     29             return;
     30         }
     31  32         // Sort by previously determined @Order value, if applicable
     33         // 配置类可以按照顺序加载
     34         Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
     35             @Override
     36             public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
     37                 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
     38                 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
     39                 return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
     40             }
     41         });
     42  43         // Detect any custom bean name generation strategy supplied through the enclosing application context
     44         SingletonBeanRegistry sbr = null;
     45         if (registry instanceof SingletonBeanRegistry) {
     46             sbr = (SingletonBeanRegistry) registry;
     47             if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
     48                 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
     49                 this.componentScanBeanNameGenerator = generator;
     50                 this.importBeanNameGenerator = generator;
     51             }
     52         }
     53  54         // Parse each @Configuration class
     55         ConfigurationClassParser parser = new ConfigurationClassParser(
     56                 this.metadataReaderFactory, this.problemReporter, this.environment,
     57                 this.resourceLoader, this.componentScanBeanNameGenerator, registry);
     58  59         Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
     60         Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
     61         do {
     62             // 解析配置类,完成这一步流程后,在其内部对各种配置信息,包装为一个ConfigurationClass的集合
     63             // 在加载bean的过程中,实际上也是对这个集合进行各种操作,如:从@Bean方法加载bean、@Import导入配置等等
     64             parser.parse(candidates);
     65             parser.validate();
     66  67             Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
     68             configClasses.removeAll(alreadyParsed);
     69  70             // Read the model and create bean definitions based on its content
     71             if (this.reader == null) {
     72                 this.reader = new ConfigurationClassBeanDefinitionReader(
     73                         registry, this.sourceExtractor, this.resourceLoader, this.environment,
     74                         this.importBeanNameGenerator, parser.getImportRegistry());
     75             }
     76             // 对ConfigurationClassParser持有的配置信息集合进行bean的加载。
     77             // 至此,需要注册到IOC容器的所有bean都已注册完毕
     78             this.reader.loadBeanDefinitions(configClasses);
     79             alreadyParsed.addAll(configClasses);
     80  81             candidates.clear();
     82             if (registry.getBeanDefinitionCount() > candidateNames.length) {
     83                 String[] newCandidateNames = registry.getBeanDefinitionNames();
     84                 Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
     85                 Set<String> alreadyParsedClasses = new HashSet<String>();
     86                 for (ConfigurationClass configurationClass : alreadyParsed) {
     87                     alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
     88                 }
     89                 for (String candidateName : newCandidateNames) {
     90                     if (!oldCandidateNames.contains(candidateName)) {
     91                         BeanDefinition bd = registry.getBeanDefinition(candidateName);
     92                         if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
     93                                 !alreadyParsedClasses.contains(bd.getBeanClassName())) {
     94                             candidates.add(new BeanDefinitionHolder(bd, candidateName));
     95                         }
     96                     }
     97                 }
     98                 candidateNames = newCandidateNames;
     99             }
    100         }
    101         while (!candidates.isEmpty());
    102 103         // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    104         if (sbr != null) {
    105             if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    106                 sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    107             }
    108         }
    109 110         if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    111             ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    112         }
    113     }
    114 115 }

     

  • 相关阅读:
    InfoPath 发布表单到SharePoint库报错
    在log4net中控制nhibernate输出
    微信扫一扫(wx.scanQRCode)功能新手可能遇到的问题
    3.Zookeeper的安装和配置(集群模式)
    1.配置HDFS HA (高可用)
    2.Zookeeper工作原理(详细)
    1.Zookeeper 定义与工作原理
    js 获取元素的几种方法
    弹出层居中
    XUACompatible
  • 原文地址:https://www.cnblogs.com/magic-sea/p/11701478.html
Copyright © 2011-2022 走看看