Spring BeanDefinition使用介绍
作者:程序员小潘
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是一个接口,本身的类图还是比较简单的,继承了AttributeAccessor
和BeanMetadataElement
接口。
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的代码也同样极其简单,只是提供了两个属性metadata
和factoryMethodMetadata
来记录注解元数据和工厂方法元数据而已。
2.7 其它实现
本文着重分析了AnnotatedGenericBeanDefinition这一条分支,实际上在Spring中BeanDefinition还有很多实现类,例如:
- RootBeanDefinition:ChildBeanDefinition:基于父Bean的子BeanDefinition。
- ConfigurationClassBeanDefinition:加了@Bean注解的BeanDefinition。
- ScannedGenericBeanDefinition:加了@Component及其派生注解的BeanDefinition。
到此这篇关于Spring BeanDefinition使用介绍的文章就介绍到这了,更多相关Spring BeanDefinition内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
- SpringIOC BeanDefinition的加载流程详解
- Spring注解驱动之BeanDefinitionRegistryPostProcessor原理解析
- 如何利用Spring把元素解析成BeanDefinition对象
- Spring超详细讲解创建BeanDefinition流程
- BeanDefinitionRegistryPostProcessor如何动态注册Bean到Spring
- Spring Bean生命周期之BeanDefinition的合并过程详解
- springboot自动扫描添加的BeanDefinition源码实例详解
- Spring应用抛出NoUniqueBeanDefinitionException异常的解决方案