Spring BeanDefinition使用介绍
作者:程序员小潘 发布时间:2023-11-24 10:29:10
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。
来源:https://javap.blog.csdn.net/article/details/128352190
猜你喜欢
- Bean的自动装配自动装配说明自动装配是使用spring满足bean依赖的一种方法spring会在应用上下文中为某个bean寻找其依赖的be
- 一、流程和任务的关系以下是一个简单的请假流程图,其中有一个开始事件,两个用户任务,一个结束事件。启动流程后,activiti会自动创建第一个
- 这篇文章主要介绍了SpringBoot下如何实现支付宝接口的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 了解YMP框架YMP于2014年10月25日正式发布1.0版本,在此之前就已在实际项目中得到广泛使用,从最初仅限团队内部使用,到合作伙伴的开
- JPA Specification常用查询+排序1.第一步:继承父类public interface TblCarton2RCardLogR
- [LeetCode] 9. Palindrome Number 验证回文数字Determine whether an integer is
- 如下所示:package cn.sunzn.md5;import java.security.MessageDigest;import ja
- 背景最近好几个项目在运行过程中客户都提出文件上传大小的限制能否设置的大一些,用户经常需要上传好几个G的资料文件,如图纸,视频等,并且需要在上
- 【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都
- 前言在看一本关于高性能编程的时候发现 Java8 中关于接口的新特性的介绍,这个特性是真的棒,解决了一个接口中有多个方法,但并不想实现该接口
- 所谓文件的断点续传,就是一个线程传输文件,另一个线程控制传输标识,以达到暂停文件效果、恢复文件上传的效果。本demo使用最基本的线程之间的通
- 1 依赖配置<parent> <groupId>org.springframework.b
- 使用限制JDBC未支持列表Sharding-JDBC暂时未支持不常用的JDBC方法。DataSource接口不支持timeout相关操作Co
- 多数据源的目的在于一个代码模块可调用多个数据库的数据进行某些业务操作。MyBatis-Plus开发者写了一个多数据源叫dynamic-dat
- ArrayList集合的创建非泛型创建ArrayList集合对象,可以添加任意Object子类元素至集合//非泛型创建的ArrayList集
- 面试题1:说一下抽象类和接口有哪些区别?正经回答:抽象类和接口的主要区别:从设计层面来说,抽象类是对类的抽象,是一种模板设计;接口是行为的抽
- 前言:我们每天都在编写Java代码,编译,执行。很多人已经知道Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.cl
- 上篇介绍了几种图表的公共组件X、Y轴、背景Board的绘制。这章节介绍柱状图表的绘制,相对其它图表而言简单一些,这里主要介绍图表主体的绘制,
- 一、系统启动后注入配置package com.example.config;import org.springframework.beans
- 1.springboot启动过程中,首先会收集需要加载的bean的定义,作为BeanDefinition对象,添加到BeanFactory中