Spring源码 --- BeanDefinition接口,及其各种子类结构关系

BeanDefinition就是用于描叙Spring中的Bean  

Spring中关于一个Bean的基本描叙接口 --

        BeanDefinition的定义:

                                        

       BeanMetadataElement接口:获取Source。

public interface BeanMetadataElement {

   /**
    * Return the configuration source {@code Object} for this metadata element
    * (may be {@code null}).
    */
   @Nullable
   Object getSource();

}

   AttributeAccessor:   

public interface AttributeAccessor {

   void setAttribute(String name, @Nullable Object value);

   @Nullable
   Object getAttribute(String name);

   @Nullable
   Object removeAttribute(String name);

   boolean hasAttribute(String name);

   String[] attributeNames();

}

      其基本实现类:BeanMetadataAttributeAccessor:     

public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {

   private final Map<String, Object> attributes = new LinkedHashMap<>(0);

   @Override
   public void setAttribute(String name, @Nullable Object value) {
      Assert.notNull(name, "Name must not be null");
      if (value != null) {
         this.attributes.put(name, value);
      }
      else {
         removeAttribute(name);
      }
   }
..................
}

然后是其Abstract实现:AbstractBeanDefinition

   此类定义了注入Bean的几种类型:

/**
 * Constant that indicates no autowiring at all.
 * @see #setAutowireMode
 */
public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;

public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;

public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;

public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;

@Deprecated
public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;

第一个是默认的,然后最后一个AUTOWIRE_AUTODETECT 已经是过时的了@Deprecated。在使用的这几种类型看名字也知道其是什么类型的了。而过时的那种,我们找到其中的一个使用的地方是会将其转换为转换为“AUTOWIRE_BY_TYPE”、“AUTOWIRE_CONSTRUCTOR”:

public int getResolvedAutowireMode() {
   if (this.autowireMode == AUTOWIRE_AUTODETECT) {
      // Work out whether to apply setter autowiring or constructor autowiring.
      // If it has a no-arg constructor it's deemed to be setter autowiring,
      // otherwise we'll try constructor autowiring.
      Constructor<?>[] constructors = getBeanClass().getConstructors();
      for (Constructor<?> constructor : constructors) {
         if (constructor.getParameterCount() == 0) {
            return AUTOWIRE_BY_TYPE;
         }
      }
      return AUTOWIRE_CONSTRUCTOR;
   }
   else {
      return this.autowireMode;
   }
}

     再AbstractBeanDefinition的直接子类:

               ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition、AnnotatedBeanDefinition

    这四个的区别:

     

     AnnotatedBeanDefinition

        就是描叙通过注解的方式注入的BeanDefinition

     RootBeanDefinition

       看下RootBeanDefinition的注释:

A root bean definition represents the merged bean definition that backs ,a specific bean in a Spring BeanFactory at runtime。

       用不太好的英语看下其主要意思。其是一个merged bean definition(合并的Bean定义),在BeanFactory at runtime(BeanFactory 运行使用的时候)。

  我们看下BeanFactory在获取Bean的时候:

     在AbstractBeanFactory通过Bean名称第一次获取对应Bean的getBean(String name)方法的过程中。是会调一个方法:

           final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

         最后会调到这段代码

getMergedBeanDefinition(
      String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
{
   ..............  if (bd.getParentName() == null) {  if (bd instanceof RootBeanDefinition) {     mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
  }
  else {
     mbd = new RootBeanDefinition(bd);
  }
 ..........
}
RootBeanDefinition(BeanDefinition original) {
   super(original);
}
protected AbstractBeanDefinition(BeanDefinition original) {
   setParentName(original.getParentName());
   setBeanClassName(original.getBeanClassName());
   setScope(original.getScope());
   setAbstract(original.isAbstract());
   setLazyInit(original.isLazyInit());
    ..........
}

也就是说,你在获取的Bean的时候,不管是哪种BeanDefinition的定义,如果不是RootBeanDefinition,都会转换为RootBeanDefinition。

     ChildBeanDefinition

public class ChildBeanDefinition extends AbstractBeanDefinition {
   @Nullable
   private String parentName;
    .........
   @Override
   public void setParentName(@Nullable String parentName) {
      this.parentName = parentName;
   }
   @Override
   @Nullable
   public String getParentName() {
      return this.parentName;
   }
       ...........
}

其会有一个有父的BeanDefinition。而前面的RootBeanDefinition是没有parentName的(因为在获取Bean的时候其他的类型都是需要归并为RootBeanDefinition来最终使用):

public class RootBeanDefinition extends AbstractBeanDefinition {
    ......
    @Override
    public String getParentName() {
       return null;
    }
    ..........
 }

 我们再来看其在获取Bean的时候是怎样使用的(前面是走的bd.getParentName() == null的逻辑,现在走的是下面的内容): 

if (bd.getParentName() == null) {
     .........
}
else {
   BeanDefinition pbd;
   try {
      String parentBeanName = transformedBeanName(bd.getParentName());
      if (!beanName.equals(parentBeanName)) {
         pbd = getMergedBeanDefinition(parentBeanName);
      }
      else {
         BeanFactory parent = getParentBeanFactory();
         if (parent instanceof ConfigurableBeanFactory) {
            pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
         }
     .............
          mbd = new RootBeanDefinition(pbd);
           mbd.overrideFrom(bd);
     }
}

这里的getMergedBeanDefinition就是会回到最初的获取MergedBean。这里就有有个循环调用。去获取父Bean,然后合并为RootBeanDefinition

  GenericBeanDefinition

    GenericBeanDefinition其也是有ParentName属性的。那这个GenericBeanDefinition与ChildrenBeanDefinitin的区别是什么呢?

    其两者的区别主要是ChildrenBeanDefinitin没有子类了,而GenericBeanDefinition还有子类。(目前了解的使用情况:如果一个Bean有父Bean,Spring内部在使用BeanDefinition的时候也用的是这个GenericBeanDefinition,而ChildrenBeanDefinitin在Spring源码内部,Spring一般并没有主动去创建使用这个类)。

       GenericBeanDefinition的子类:AnnotatedGenericBeanDefinition、ScannedGenericBeanDefinition

             这两个子类一个是通过注解的方式注入的Bean、例如@Configuration等这种注直接指明一个对应的注解类注入的BeanDefinition就会装配为AnnotatedGenericBeanDefinition、而通过扫描包的方式其添加的BeanDefinition就会装配为ScannedGenericBeanDefinition。我们通过代码来说明:

           AnnotatedGenericBeanDefinition:       

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
      @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
      return;
   }
...........
}

往上找这个方法的调用:

public void registerBean(Class<?> annotatedClass) {
   doRegisterBean(annotatedClass, null, null, null);
}
public class AnnotatedBeanDefinitionReader {
    ........
   public void register(Class<?>... annotatedClasses) {
      for (Class<?> annotatedClass : annotatedClasses) {
         registerBean(annotatedClass);
      }
   ............
   }

    再找个调用此方法的测试demo:     

@Test
public void annotatedBeanDefinitionReader_inheritsEnvironmentFromEnvironmentCapableBDR() {
   GenericApplicationContext ctx = new GenericApplicationContext();
   ctx.setEnvironment(prodEnv);
   new AnnotatedBeanDefinitionReader(ctx).register(Config.class);
}
@Configuration
@Import({DevConfig.class, ProdConfig.class})
static class Config {
   @Bean
   public EnvironmentAwareBean envAwareBean() {
      return new EnvironmentAwareBean();
   }
}

        ScannedGenericBeanDefinition            

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
   Set<BeanDefinition> candidates = new LinkedHashSet<>();
   try {
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
       ............
      for (Resource resource : resources) {
         if (resource.isReadable()) {
            try {
               MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
               if (isCandidateComponent(metadataReader)) {
                  ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
           ..........
}
@Test
public void testSimpleScanWithDefaultFiltersAndPrimaryLazyBean() {
   GenericApplicationContext context = new GenericApplicationContext();
   ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
   scanner.scan(BASE_PACKAGE);
   scanner.scan("org.springframework.context.annotation5");
   ..........
}

可以看到这个就是通过basePackage基本包,然后从对应包下面找到要注入的BeanDefinition会描叙为ScannedGenericBeanDefinition。

   从成员变量的角度来说:

public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {
   private final AnnotationMetadata metadata;
   @Nullable
   private MethodMetadata factoryMethodMetadata;
    ......
}
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {
   private final AnnotationMetadata metadata;
       ..........
}

AnnotatedGenericBeanDefinition 比ScannedGenericBeanDefinition 多了一个MethodMetadata :

public interface MethodMetadata extends AnnotatedTypeMetadata {
   String getMethodName();
   String getDeclaringClassName();
   String getReturnTypeName();
   boolean isAbstract();
   boolean isStatic();
   boolean isFinal();
   boolean isOverridable();
}

      ConfigurationClassBeanDefinition:

class ConfigurationClassBeanDefinitionReader {  
     ..........
     private static class ConfigurationClassBeanDefinition extends RootBeanDefinition implements AnnotatedBeanDefinition {

      private final AnnotationMetadata annotationMetadata;

      private final MethodMetadata factoryMethodMetadata;
             ...........
   }

可以看到其是定义在ConfigurationClassBeanDefinitionReader

    那这个ConfigurationClassBeanDefinition是用来描叙哪种类型的BeanDefinition的呢。我们看下其的使用demo:

public static void main(String[] args)
{
    GenericApplicationContext listableBeanFactory = new GenericApplicationContext();
    new AnnotatedBeanDefinitionReader(listableBeanFactory).register(Config.class);
    listableBeanFactory.refresh();
    TestBean bean = listableBeanFactory.getBean(TestBean.class);
}
@Configuration
public class Config
{
    @Bean
    public TestBean getTestBean()
    {
        return new TestBean();
    }
}

可以看到通过在@Configuration 中使用@Bean会将其注册为ConfigurationClassBeanDefinition。而@Configuration是注册为前面讲的AnnotatedGenericBeanDefinition:

    

       

 

     

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值