Spring BeanDefinition使用介绍

 更新时间:2023年01月04日 14:37:25   作者:程序员小潘  
BeanDefinition是Spring框架中非常核心的概念,BeanDefinition是定义Bean的配置元信息接口,Spring根据BeanDefinition来定义Bean对象,简单说就是对Bean信息的定义

1. 前言

Spring最重要的一个概念当属Bean了,我们写的Controller、Service、Dao凡是加了对应注解交给Spring管理的,都是Spring容器中的一个Bean。把我们自己写的类变成一个Bean交给Spring管理有很多的好处,比如我们不用自己去new对象了,Spring会帮我们在适当的时候去实例化对象;再比如Spring还会维护Bean的依赖关系,自动注入依赖的对象;再比如Spring还可以基于Bean生成代理对象,来对原生的Bean进行功能上的增强等等。

在Spring源码中,有一个重要的接口BeanDefinition,它用来表示Bean的定义。比如Bean的名称、所属的Class、是否需要延迟实例化,是单例还是原型?等等信息。不管你是通过xml来配置,还是JavaConfig的方式,还是基于注解的方式,在Spring看来它们都是一个BeanDefinition

2. BeanDefinition

BeanDefinition是一个接口,本身的类图还是比较简单的,继承了AttributeAccessorBeanMetadataElement接口。

2.1 AttributeAccessor

AttributeAccessor接口代表一个属性访问器,它的作用是可以给Bean附加一些自定义的属性,并提供访问方法。

例如:originalTargetClass属性代表AOP被代理的原始Class对象;preserveTargetClass属性代表是否基于类进行代理。

AttributeAccessorSupport是其中一个实现类,它底层通过LinkedHashMap来存储这些附加属性。

public interface AttributeAccessor {
	void setAttribute(String name, @Nullable Object value);
	Object getAttribute(String name);
	Object removeAttribute(String name);
	boolean hasAttribute(String name);
	String[] attributeNames();
}

2.2 BeanMetadataElement

BeanMetadataElement接口我也不是很清楚具体作用是啥,网上对它的介绍也比较少。

public interface BeanMetadataElement {
	/**
	 * 对于常规Bean,可以获得Bean对应的Resource
	 */
	@Nullable
	Object getSource();
}

经过实验发现,对于常规的Bean来说,可以通过getSource()方法获取Bean对应的资源。例如:现在有一个BeanDefinition它的BeanClass来自ClassPath下的包,getSource()方法可以获取到这个Class文件对应的FileSystemResource资源。

2.3 BeanDefinition

终于看到主角了,BeanDefinition还是一个接口,它提供了一系列方法来读写Bean的一些属性定义,方法名基本都能见名知意,注释里已经把方法的作用写上了。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
  /**
* 父Bean的name 对应XML里的 <bean parent=""> 配置
*/
  void setParentName(@Nullable String parentName);
  String getParentName();
  /**
* BeanClassName 对应XML里的 <bean class=""> 配置
*/
  void setBeanClassName(@Nullable String beanClassName);
  String getBeanClassName();
  /**
* Bean的作用域 单例/原型
*/
  void setScope(@Nullable String scope);
  String getScope();
  /**
* 是否延迟加载
* 默认为fale,容器启动时自动实例化单例Bean
* 设置为true,则在getBean时再实例化
*/
  void setLazyInit(boolean lazyInit);
  boolean isLazyInit();
  /**
* 依赖的其它Bean
* BeanFactory保证先实例化依赖的Bean
*/
  void setDependsOn(@Nullable String... dependsOn);
  String[] getDependsOn();
  /**
* 当前Bean是否作为其它Bean依赖注入时的候选Bean,默认为true
* Spring根据Type注入时,如果存在多个实现类,会抛出异常
* 通过将autowireCandidate设置为false,该Bean将不再是依赖注入时的候选Bean
* 根据name注入时,不受影响
*/
  void setAutowireCandidate(boolean autowireCandidate);
  boolean isAutowireCandidate();
  /**
* 依赖注入 存在多个候选Bean时,优先注入primary=true的
*/
  void setPrimary(boolean primary);
  boolean isPrimary();
  void setFactoryBeanName(@Nullable String factoryBeanName);
  String getFactoryBeanName();
  void setFactoryMethodName(@Nullable String factoryMethodName);
  String getFactoryMethodName();
  /**
* Bean的构造函数参数值
*/
  ConstructorArgumentValues getConstructorArgumentValues();
  default boolean hasConstructorArgumentValues() {
    return !getConstructorArgumentValues().isEmpty();
  }
  /**
* 获取Bean实例的属性值
*/
  MutablePropertyValues getPropertyValues();
  default boolean hasPropertyValues() {
    return !getPropertyValues().isEmpty();
  }
  /**
* Bean初始化的方法名
*/
  void setInitMethodName(@Nullable String initMethodName);
  @Nullable
  String getInitMethodName();
  /**
* Bean销毁的方法名
*/
  void setDestroyMethodName(@Nullable String destroyMethodName);
  String getDestroyMethodName();
  void setRole(int role);
  int getRole();
  /**
* Bean的描述
*/
  void setDescription(@Nullable String description);
  String getDescription();
  /**
* 是否是单例的
*/
  boolean isSingleton();
  /**
* 是否是原型的
*/
  boolean isPrototype();
  /**
* 是否是抽象Bean,如果是将不会实例化
*/
  boolean isAbstract();
  @Nullable
  String getResourceDescription();
  /**
* 获取原始的BeanDefinition
*/
  @Nullable
  BeanDefinition getOriginatingBeanDefinition();
}

2.4 AbstractBeanDefinition

AbstractBeanDefinition是一个抽象类,实现了绝大多数BeanDefinition的功能,源码也很简单,通过大量属性来记录BeanDefinition对应方法设置的属性值,代码就不贴了。

2.5 GenericBeanDefinition

GenericBeanDefinition是一个类,它是BeanDefinition的标准实现,继承自AbstractBeanDefinition。刚刚已经说过了,由于AbstractBeanDefinition已经实现了绝大多数方法了,所以GenericBeanDefinition的代码也极其简单,只实现了一个读写parentName的方法。

2.6 AnnotatedGenericBeanDefinition

顾名思义,AnnotatedGenericBeanDefinition是一个基于注解的BeanDefinition标准实现,它继承自GenericBeanDefinition,已经获得了BeanDefinition完整的能力了。只不过,由于是基于注解的标准实现,所以它还实现了AnnotatedBeanDefinition接口,以此来获得获取注解元数据的能力。

public interface AnnotatedBeanDefinition extends BeanDefinition {
  // 获取注解元数据
  AnnotationMetadata getMetadata();
  // 获取工厂方法元数据的能力
  MethodMetadata getFactoryMethodMetadata();
}

AnnotatedGenericBeanDefinition的代码也同样极其简单,只是提供了两个属性metadatafactoryMethodMetadata来记录注解元数据和工厂方法元数据而已。

2.7 其它实现

本文着重分析了AnnotatedGenericBeanDefinition这一条分支,实际上在Spring中BeanDefinition还有很多实现类,例如:

  • RootBeanDefinition:ChildBeanDefinition:基于父Bean的子BeanDefinition。
  • ConfigurationClassBeanDefinition:加了@Bean注解的BeanDefinition。
  • ScannedGenericBeanDefinition:加了@Component及其派生注解的BeanDefinition。

到此这篇关于Spring BeanDefinition使用介绍的文章就介绍到这了,更多相关Spring BeanDefinition内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于SpringBoot解决CORS跨域的问题(@CrossOrigin)

    基于SpringBoot解决CORS跨域的问题(@CrossOrigin)

    这篇文章主要介绍了基于SpringBoot解决CORS跨域的问题(@CrossOrigin),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • SpringBoot+Email发送邮件的实现示例

    SpringBoot+Email发送邮件的实现示例

    Spring Boot提供了简单而强大的邮件发送功能,本文主要介绍了SpringBoot+Email发送邮件的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • 基于Spring实现文件上传功能

    基于Spring实现文件上传功能

    这篇文章主要为大家详细介绍了Spring实现文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • MyBatis中#{}和${}的区别详解

    MyBatis中#{}和${}的区别详解

    mybatis和ibatis总体来讲都差不多的。下面小编给大家探讨下mybatis中#{}和${}的区别,感兴趣的朋友一起学习吧
    2016-08-08
  • 浅谈Java向下转型的意义

    浅谈Java向下转型的意义

    这篇文章主要介绍了浅谈Java向下转型的意义,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 解决mybatis-plus自动配置的mapper.xml与java接口映射问题

    解决mybatis-plus自动配置的mapper.xml与java接口映射问题

    这篇文章主要介绍了解决mybatis-plus自动配置的mapper.xml与java接口映射问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • log4j2日志异步打印(实例讲解)

    log4j2日志异步打印(实例讲解)

    下面小编就为大家带来一篇log4j2日志异步打印(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • spring security中Authority、Role的区别及说明

    spring security中Authority、Role的区别及说明

    这篇文章主要介绍了spring security中Authority、Role的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • SpringBoot开发详解之Controller接收参数及参数校验

    SpringBoot开发详解之Controller接收参数及参数校验

    数据校验是为了使系统更完整,数据更精确,同时也有利于维护数据的安全性,下面这篇文章主要给大家介绍了关于SpringBoot开发详解之Controller接收参数及参数校验的相关资料,需要的朋友可以参考下
    2022-03-03
  • mybatis插入后返回主键id的3种方式图解

    mybatis插入后返回主键id的3种方式图解

    这篇文章主要给大家介绍了关于mybatis插入后返回主键id的3种方式,很多时候,在向数据库插入数据时,需要保留插入数据的,以便进行后续的操作或者将存入其他表作为外键,需要的朋友可以参考下
    2023-08-08

最新评论