qidao123.com技术社区-IT企服评测·应用市场

标题: spring启动流程 (3) BeanDefinition详解 [打印本页]

作者: 缠丝猫    时间: 2023-7-4 08:43
标题: spring启动流程 (3) BeanDefinition详解
BeanDefinition在Spring初始化阶段保存Bean的元数据信息,包括Class名称、Scope、构造方法参数、属性值等信息,本文将介绍一下BeanDefinition接口、重要的实现类,以及在Spring中的使用示例。
BeanDefinition接口

用于描述了一个Bean实例,该Bean实例具有属性、构造方法参数以及由具体实现提供的其他信息。
这是一个基础接口:主要目的是允许BeanFactoryPostProcessor获取和修改Bean实例属性和其他元数据。
封装以下信息:

AbstractBeanDefinition类

实现了BeanDefinition接口,具体的、完整的BeanDefinition基类,抽取出GenericBeanDefinition、RootBeanDefinition和ChildBeanDefinition的公共属性。
扩展的属性:
RootBeanDefinition类

继承AbstractBeanDefinition类。
RootBeanDefinition表示在运行时支持BeanFactory中指定Bean的合并BeanDefinition。它可能是由多个相互继承的原始BeanDefinition创建的,通常注册为GenericBeanDefinitions。RootBeanDefinition本质上是运行时的"统一"RootBeanDefinition视图。
RootBeanDefinition也可以用于在配置阶段注册各个BeanDefinition。然而,自Spring2.5以来,以编程方式注册BeanDefinition的首选方式是GenericBeanDefinition类。GenericBeanDefinition的优势是允许动态定义父依赖项,而不是将角色硬编码为RootBeanDefinition。
扩展的属性:
GenericBeanDefinition类

继承AbstractBeanDefinition类。
GenericBeanDefinition是用于构建标准BeanDefinition的一站式组件。与其他BeanDefinition一样,它允许指定一个类以及可选的构造方法参数和属性。另外,从父BeanDefinition派生可以通过parentName属性灵活配置。
通常,使用GenericBeanDefinition类来注册用户可见的BeanDefinition,后置处理器可能会对其进行操作,甚至可能重新配置parentName属性。如果父子关系恰好是预先确定的,请使用RootBeanDefinition和ChildBeanDefinition。
AnnotatedBeanDefinition接口

继承BeanDefinition接口。
扩展BeanDefinition接口,提供Bean的AnnotationMetadata,而不需要加载该类。
  1. public interface AnnotatedBeanDefinition extends BeanDefinition {
  2.         /**
  3.          * Obtain the annotation metadata (as well as basic class metadata)
  4.          * for this bean definition's bean class.
  5.          */
  6.         AnnotationMetadata getMetadata();
  7.         /**
  8.          * Obtain metadata for this bean definition's factory method, if any.
  9.          */
  10.         MethodMetadata getFactoryMethodMetadata();
  11. }
复制代码
ScannedGenericBeanDefinition类

GenericBeanDefinition类的扩展,基于ASM ClassReader,实现了AnnotatedBeanDefinition接口,可以获取注解元数据。
这个类不会提前加载Bean Class。它从.class文件检索所有相关的元数据,并使用ASM ClassReader进行解析。
  1. public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {
  2.         private final AnnotationMetadata metadata;
  3.         /**
  4.          * Create a new ScannedGenericBeanDefinition for the class that the
  5.          * given MetadataReader describes.
  6.          * @param metadataReader the MetadataReader for the scanned target class
  7.          */
  8.         public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
  9.                 this.metadata = metadataReader.getAnnotationMetadata();
  10.                 setBeanClassName(this.metadata.getClassName());
  11.                 setResource(metadataReader.getResource());
  12.         }
  13.         @Override
  14.         public final AnnotationMetadata getMetadata() {
  15.                 return this.metadata;
  16.         }
  17.         @Override
  18.         public MethodMetadata getFactoryMethodMetadata() {
  19.                 return null;
  20.         }
  21. }
复制代码
AnnotatedGenericBeanDefinition类

GenericBeanDefinition类的扩展,实现了AnnotatedBeanDefinition接口,可以获取注解元数据。
  1. public class AnnotatedGenericBeanDefinition
  2.                 extends GenericBeanDefinition implements AnnotatedBeanDefinition {
  3.         private final AnnotationMetadata metadata;
  4.         private MethodMetadata factoryMethodMetadata;
  5.         public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
  6.                 setBeanClass(beanClass);
  7.                 this.metadata = AnnotationMetadata.introspect(beanClass);
  8.         }
  9.         public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
  10.                 if (metadata instanceof StandardAnnotationMetadata) {
  11.                         setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
  12.                 } else {
  13.                         setBeanClassName(metadata.getClassName());
  14.                 }
  15.                 this.metadata = metadata;
  16.         }
  17.         public AnnotatedGenericBeanDefinition(
  18.                         AnnotationMetadata metadata,
  19.                         MethodMetadata factoryMethodMetadata) {
  20.                 this(metadata);
  21.                 setFactoryMethodName(factoryMethodMetadata.getMethodName());
  22.                 this.factoryMethodMetadata = factoryMethodMetadata;
  23.         }
  24.         @Override
  25.         public final AnnotationMetadata getMetadata() {
  26.                 return this.metadata;
  27.         }
  28.         @Override
  29.         public final MethodMetadata getFactoryMethodMetadata() {
  30.                 return this.factoryMethodMetadata;
  31.         }
  32. }
复制代码
Spring中使用BeanDefinition示例

注册componentClasses

AnnotationConfigApplicationContext启动代码:
  1. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
  2. applicationContext.register(ServiceConfig.class);
  3. applicationContext.refresh();
复制代码
AnnotationConfigApplicationContext在启动时可以使用register方法注册@Configuration类,本小节将从这个方法入手看一个BeanDefinition的使用示例:
[code]public void register(Class... componentClasses) {        Assert.notEmpty(componentClasses, "At least one component class must be specified");        this.reader.register(componentClasses);}// reader.register(...)public void register(Class... componentClasses) {        for (Class componentClass : componentClasses) {                registerBean(componentClass);        }}private  void doRegisterBean(Class beanClass, String name,                Class




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4