阅读 53
【Spring源码系列】Bean的定义-BeanDefinition

【Spring源码系列】Bean的定义-BeanDefinition

定义Bean对象有哪些方式?

在Spring容器中我们使用的一个一个的Bean,那我们定义Bean的形式有哪些呢?

  • <bean/>
  • @Bean
  • @Component/@Service/@Controller

除了上述方式我们还可以通过BeanDefinition这个类来定义Bean对象

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 生成一个BeanDefinition对象,并设置beanClass为UserService.class,并注册到ApplicationContext中
AbstractBeanDefinition beanDefinition =BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(UserService.class);
context.registerBeanDefinition("userService", beanDefinition);
System.out.println(context.getBean("userService"));
// 设置作用域
beanDefinition.setScope("prototype"); 
// 设置初始化方法
beanDefinition.setInitMethodName("init");
// 设置懒加载
beanDefinition.setLazyInit(true); 
复制代码

BeanDefinition

那么怎么理解BeanDefinition?

BeanDefinition是Bean在Spring中的描述,是Bean在Spring中的定义形态,有了BeanDefinition我们就可以创建Bean。BeanDefinition与Bean的关系可以理解为类与对象的关系,类在Spring的数据结构就是BeanDefinition,根据BeanDefinition得到的对象就是我们需要的Bean。

BeanDefinition中存在很多属性用来描述一个Bean的特点:

  • class,表示Bean类型
  • scope,表示Bean作用域,单例或原型等
  • lazyInit:表示Bean是否是懒加载
  • initMethodName:表示Bean初始化时要执行的方法
  • destroyMethodName:表示Bean销毁时要执行的方法
  • 还有很多...

BeanDefinition是一个接口,具体的接口内容如下:


package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * A BeanDefinition describes a bean instance, which has property values,
 * constructor argument values, and further information supplied by
 * concrete implementations.
 *
 * <p>This is just a minimal interface: The main intention is to allow a
 * {@link BeanFactoryPostProcessor} to introspect and modify property values
 * and other bean metadata.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 19.03.2004
 * @see ConfigurableListableBeanFactory#getBeanDefinition
 * @see org.springframework.beans.factory.support.RootBeanDefinition
 * @see org.springframework.beans.factory.support.ChildBeanDefinition
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

   //标准单例作用域的作用域标识符:“singleton”。
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   //标准原型作用域的范围标识符:“prototype”
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


   // Bean角色
   int ROLE_APPLICATION = 0; //用户自定义
   int ROLE_SUPPORT = 1;     //来源于配置文件
   int ROLE_INFRASTRUCTURE = 2; //Spring内部的


  //配置 /获取父BeanDefinition的名称 XML中的 <bean parent="">
   void setParentName(@Nullable String parentName);
   @Nullable
   String getParentName();

   //配置/获取 Bean 的 Class 全路径 XML 中的 <bean class="">
   void setBeanClassName(@Nullable String beanClassName);
   @Nullable
   String getBeanClassName();

   //配置/获取 Bean 的作用域 XML中的 <bean scope=""> 配置
   void setScope(@Nullable String scope);
   @Nullable
   String getScope();

  //配置 / 获取 Bean 是否懒加载(默认false,立马加载)  XML 中的 <bean lazy-init="">
   void setLazyInit(boolean lazyInit);
   boolean isLazyInit();

   //配置/获取 Bean 的依赖对象 XML中的 <bean depends-on="">
   void setDependsOn(@Nullable String... dependsOn);
   @Nullable
   String[] getDependsOn();

   //配置/获取 Bean 是否是自动装配的候选者 默认为 true XML中的 <bean autowire-candidate="">
   void setAutowireCandidate(boolean autowireCandidate);
   boolean isAutowireCandidate();

   //了多个可注入bean,那么则选择被Primary标记的bean/获取当前 Bean 是否为首选的 Bean XML中的 <bean primary="">
   void setPrimary(boolean primary);
   boolean isPrimary();

   // 配置/获取 FactoryBean 的名字 XML中的<bean factory-bean="">
   void setFactoryBeanName(@Nullable String factoryBeanName);
   @Nullable
   String getFactoryBeanName();

   // FactoryMethod 的名字,可以是某个实例的方法(和factoryBean配合使用) //也可以是静态方法。 XML 中的<bean factory-method="">
   void setFactoryMethodName(@Nullable String factoryMethodName);
   @Nullable
   String getFactoryMethodName();

   //返回该 Bean 构造方法的参数值
   ConstructorArgumentValues getConstructorArgumentValues();

   //判断 getConstructorArgumentValues 是否是空对象。
   default boolean hasConstructorArgumentValues() {
      return !getConstructorArgumentValues().isEmpty();
   }

   //获取普通属性的集合
   MutablePropertyValues getPropertyValues();

   //判断 getPropertyValues 是否为空对象
   default boolean hasPropertyValues() {
      return !getPropertyValues().isEmpty();
   }

   // 配置/获取 Bean 的初始化方法 XML中的<bean init-method="">
   void setInitMethodName(@Nullable String initMethodName);
   @Nullable
   String getInitMethodName();

   // 配置/获取 Bean 的销毁方法 XML中的<bean destroy-method="">
   void setDestroyMethodName(@Nullable String destroyMethodName);
   @Nullable
   String getDestroyMethodName();

   /**
    * //配置/获取 Bean的角色
    * @see #ROLE_APPLICATION
    * @see #ROLE_SUPPORT
    * @see #ROLE_INFRASTRUCTURE
    */
   void setRole(int role);
   int getRole();

   //配置/获取 Bean 的描述
   void setDescription(@Nullable String description);
   @Nullable
   String getDescription();


   // Read-only attributes

   /**
    * Return a resolvable type for this bean definition,
    * based on the bean class or other specific metadata.
    * <p>This is typically fully resolved on a runtime-merged bean definition
    * but not necessarily on a configuration-time definition instance.
    * @return the resolvable type (potentially {@link ResolvableType#NONE})
    * @since 5.2
    * @see ConfigurableBeanFactory#getMergedBeanDefinition
    */
   ResolvableType getResolvableType();

   //是否为单例
   boolean isSingleton();

   // 是否为原型
   boolean isPrototype();

   //是否抽象 XML 中的<bean abstract="true">
   boolean isAbstract();

   /**
    * Return a description of the resource that this bean definition
    * came from (for the purpose of showing context in case of errors).
    */
   @Nullable
   String getResourceDescription();

   // 如果当前 BeanDefinition 是一个代理对象,那么该方法可以用来返回原始的 BeanDefinition
   @Nullable
   BeanDefinition getOriginatingBeanDefinition();

}
复制代码

从上边的属性和方法来看,BeanDefinition对于一个Bean的描述做了较为完整的一套约束,这为后续的子类提供了最近本的职责和属性。而通过<bean/>@Bean@Component等声明式的方式所定义的Bean最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。

文章分类
后端
文章标签