Spring BeanDefinition使用介绍

目录
  • 1. 前言
  • 2. BeanDefinition
    • 2.1 AttributeAccessor
    • 2.2 BeanMetadataElement
    • 2.3 BeanDefinition
    • 2.4 AbstractBeanDefinition
    • 2.5 GenericBeanDefinition
    • 2.6 AnnotatedGenericBeanDefinition
    • 2.7 其它实现

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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring应用抛出NoUniqueBeanDefinitionException异常的解决方案

    前言 我们在开发Spring应用时可能会不小心注入两个相同类型的Bean,比如实现了两个相同Service接口的类,示例伪代码如下: interface SampleService {   String getName(); } class ServiceA implements SampleService{    String getName(){      return "john";    } } class ServiceB implements SampleService{

  • springboot自动扫描添加的BeanDefinition源码实例详解

    1. springboot启动过程中,首先会收集需要加载的bean的定义,作为BeanDefinition对象,添加到BeanFactory中去. 由于BeanFactory中只有getBean之类获取bean对象的方法,所以将将BeanDefinition添加到BeanFactory中,是通过BeanDefinitionRegistry接口的void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) t

  • 如何利用Spring把元素解析成BeanDefinition对象

    目录 前言 1.BeanDefinition 2.BeanDefinitionParserDelegate 2.1.parseBeanDefinitionElement 2.2.parseBeanDefinitionElement 2.3 parseBeanDefinitionAttributes 2.4 parseConstructorArgElement 3 总结 前言 spring中解析元素最重要的一个对象应该就属于 BeanDefinition了:这个Spring容器中最基本的内部数据结

  • Spring超详细讲解创建BeanDefinition流程

    目录 一.前期准备 1.1 环境依赖 1.2 实体类 1.3 applicationContext.xml 1.4 测试代码 二.探究过程 2.1 目标 2.2 BeanDefinition的创建过程 2.2.1 回顾bean对象的创建 2.2.2 AbstractApplicationContext 2.2.3 AbstractXmlApplicationContext 2.2.4 AbstractBeanDefinitionReader 2.2.5 XmlBeanDefinitionRead

  • SpringIOC BeanDefinition的加载流程详解

    目录 一.前言 二. BeanDefinition 的体系 2.1 体系概览 2.2 BeanDefinition 的作用 三. BeanDefinition 的载入 3.1 载入的入口 3.2 保存的逻辑 3.3 使用的方式 总结 一.前言 这一篇来看看 SpringIOC 里面的一个细节点 , 来简单看看 BeanDefinition 这个对象 , 以及有没有办法对其进行定制. CASE 备份 :  gitee.com/antblack/ca… 二. BeanDefinition 的体系 2

  • Spring Bean生命周期之BeanDefinition的合并过程详解

    目录 前言 BeanDefinition的合并源码分析 总结 写在前面 注:本文章使用的 SpringBoot 版本为 2.2.4.RELEASE,其 Spring 版本为 5.2.3.RELEASE 前言 书接上文,BeanDefinition注册到IoC容器后,紧接着就是要使用Bean了,要使用必须先要获取Bean,这里我们就以DefaultListableBeanFactory#getBean方法来引出本次讨论的内容:BeanDefinition的合并 通过前面的章节我们了解到了BeanD

  • BeanDefinitionRegistryPostProcessor如何动态注册Bean到Spring

    目录 1.理论 2.实战代码 总结下 1.理论 一般如果想将类注册到spring容器,让spring来完成实例化,常用方式如下: xml中通过bean节点来配置: 使用@Service.@Controller.@Conponent等注解. 最近在研究通过Spring初始化时扫描自定义注解,查到了通过实现BeanDefinitionRegistryPostProcessor获取Bean,从而获得自定义注解. Spring支持我们通过代码来将指定的类注册到spring容器中. Spring容器初始化

  • Spring注解驱动之BeanDefinitionRegistryPostProcessor原理解析

    目录 BeanDefinitionRegistryPostProcessor概述 案例实践 源码分析 小结 BeanDefinitionRegistryPostProcessor概述 可以看到BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口. 注释中说执行时机是所有合法的bean定义已经加载,但是还没实例化. 看起来和BeanFactoryPostProcessor执行时机差不多,但是BeanFactoryPostP

  • Spring BeanDefinition使用介绍

    目录 1. 前言 2. BeanDefinition 2.1 AttributeAccessor 2.2 BeanMetadataElement 2.3 BeanDefinition 2.4 AbstractBeanDefinition 2.5 GenericBeanDefinition 2.6 AnnotatedGenericBeanDefinition 2.7 其它实现 1. 前言 Spring最重要的一个概念当属Bean了,我们写的Controller.Service.Dao凡是加了对应注

  • Java中批处理框架spring batch详细介绍

    spring batch简介 spring batch是spring提供的一个数据处理框架.企业域中的许多应用程序需要批量处理才能在关键任务环境中执行业务操作. 这些业务运营包括: 无需用户交互即可最有效地处理大量信息的自动化,复杂处理. 这些操作通常包括基于时间的事件(例如月末计算,通知或通信). 在非常大的数据集中重复处理复杂业务规则的定期应用(例如,保险利益确定或费率调整). 集成从内部和外部系统接收的信息,这些信息通常需要以事务方式格式化,验证和处理到记录系统中. 批处理用于每天为企业处

  • java Spring Boot的介绍与初体验

    目录 Spring Boot 介绍 系统要求 构建工具 Servlet 容器 初体验 总结 Spring Boot 介绍 Spring Boot用于创建可运行的.独立的.生产级的基于Spring的应用程序.Spring Boot对Spring和第三方库持约定大于配置的观念,以便可以轻松上手.大多数Spring Boot应用程序只需要很少的配置. Spring Boot可以通过使用java -jar或更传统的war包部署来启动Java应用程序,Spring Boot的目标是: 为所有Spring开

  • Spring DevTools的介绍

    Spring DevTools 介绍 Spring Boot包括一组额外的工具,可以使应用程序开发体验更加愉快.spring-boot-devtools模块可以包含在任何项目中,它可以节省大量的时间. 想要使用devtools支持,只需将模块依赖关系添加到你的构建中: Maven. <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>

  • Spring Data JDBC介绍及实现代码

    Spring新增了一个新的数据模块:Spring Data JDBC.Spring Data JDBC背后的想法是提供对关系数据库的访问,而无需处理JPA的复杂性.JPA提供延迟加载,缓存和脏跟踪等功能.果你需要这些功能会很很棒,但会让猜测JPA的行为比非JPA更难. 延迟加载可能会在你不需要时触发昂贵的语句,或者它可能会因异常而失败.当你想要比较一个实体的两个版本是哪个变成脏数据时,缓存可能会妨碍你,让你很难找到所有持久性操作都通过的那个点. Spring Data JDBC目标是实现更简单的

  • Spring整合Quartz实现定时任务调度的方法

    最近项目中需要实现定时执行任务,比如定时计算会员的积分.调用第三方接口等,由于项目采用spring框架,所以这里结合spring框架来介绍. 编写作业类 即普通的pojo,如下: package com.pcmall.task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TaskA { private static Logger logger = LoggerFactory.getLogger(Ta

  • Spring基础篇之初识DI和AOP

    前言 作为从事java开发的码农,Spring的重要性不言而喻,你可能每天都在和Spring框架打交道.Spring恰如其名的,给java应用程序的开发带了春天般的舒爽感觉.Spring,可以说是任何一个java开发者通往技术高阶的必备基础.当然,要学好Spring,尤其是了解Spring的底层原理并不容易,需要花费很多时间和精力来潜心的研习,并在实际的项目中不断的试错和总结,才能形成属于自己的思维理解.博主对Spring最初的认识颇浅,项目中遇到问题依靠度娘大概也能笼而统之的解决.不过呢,接触

  • Spring Framework 5.0 入门教程

    1. 为什么学习Spring? 随着对Java EE的不断接触和理解,你会发现Spring 在各个企业和项目中发挥着越来越重要的作用.掌握Spring 已成为我们IT行业生存必学的本领之一. Spring Framework 是一个开源的Java/Java EE全功能栈(full-stack)的应用程序框架,以Apache许可证形式发布,也有.NET平台上的移植版本. 该框架基于 Expert One-on-One Java EE Design and Development(ISBN 0-76

随机推荐