在spring源码中,会涉及到bean和beanDefinition这两个概念,接下来,说下什么是bean,什么是beanDefinition
class、beanDefinition、bean三者的关系
class是我们自己写的类,bean是spring经过自己的一系列处理之后。生成的,我们可以认为bean是spring容器中真正的成品,beanDefinition是对bean的一个描述信息,spring会根据beanDefinition去生成bean,所以三者的关系是:
spring首先将class转换为beanDefinition,然后再将beanDefinition转换为bean
我们通常说,spring可以通过自动扫描,完成bean的实例化,其实这里的自动扫描,是把class文件,通过扫描,转换为beanDefinition
beanDefinition的定义
我们可以看下beanDefinition的定义

可以看到,一个beanDefinition中,定义了N多个属性和方法,比如:是否是primary、是否是懒加载、dependOn属性、autowireMode自动注入属性等
所以,我们可以简单的认为,spring在扫描class的时候,会根据class文件中的注解等信息,给beanDefinition对象赋值,所以,beanDefinition是对一个类的描述
那spring在真正去初始化、实例化一个bean的时候,直接根据beanDefinition去初始化就可以,比如,在判断这个bean是根据类型注入,还是根据名字注入的时候,就直接判断autowireMode的属性值即可
spring根据beanDefinition进行初始化
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 1.获取到所有的beanDefinitionName
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 2.依次遍历所有的beanDefinitionName,进行初始化
for (String beanName : beanNames) {
// 3.在mergedBeanDefinition的时候,会根据beanName从beanDefinitionMap中获取到beanDefinition,merge之后返回
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 4.这里的getBean()是去开始对beanName对应的bean初始化
getBean(beanName);
}
}
}
}
这是spring初始化前的一个判断逻辑,在第3点注释中,可以看到,是根据beanDefinition的属性进行判断,判断当前是否是单例、是否是非抽象类等
在第4处注解中,会去真正开始初始化bean,这里就有一个疑问点了,既然在第2点这里已经对beanDefinition进行了merge,为什么在getBean()的时候,不直接传beanDefinition过去,传一个beanName,岂不是还要再根据beanName获取一遍beanDefinition?
这里其实在前面mergeBeanDefinition原理
这篇笔记中有说过,在merge之后,会把beanName和merge之后的beanDefinition存到了一个集合中,在下次再次使用到的时候,就无需再次重新merge,直接从集合中获取即可
上面这个源码我们可以看到,在初始化前,会先根据beanName解析到当前class所对应的beanDefinition信息,然后在初始化的过程中,需要进行一些判断的时候,就直接根据beanDefinition的属性进行判断
自动注入模型的判断
通常说,spring有五种注入模型
/**
* Constant that indicates no externally defined autowiring. Note that
* BeanFactoryAware etc and annotation-driven injection will still be applied.
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
int AUTOWIRE_NO = 0;
/**
* Constant that indicates autowiring bean properties by name
* (applying to all bean property setters).
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
int AUTOWIRE_BY_NAME = 1;
/**
* Constant that indicates autowiring bean properties by type
* (applying to all bean property setters).
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
int AUTOWIRE_BY_TYPE = 2;
/**
* Constant that indicates autowiring the greediest constructor that
* can be satisfied (involves resolving the appropriate constructor).
* @see #createBean
* @see #autowire
*/
int AUTOWIRE_CONSTRUCTOR = 3;
/**
* Constant that indicates determining an appropriate autowire strategy
* through introspection of the bean class.
* @see #createBean
* @see #autowire
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
* prefer annotation-based autowiring for clearer demarcation of autowiring needs.
*/
@Deprecated
int AUTOWIRE_AUTODETECT = 4;
那spring源码在处理的时候,是怎么判断是哪种注入模型呢?
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
}
上面这个是属性注入源码中的部分代码,我删减了一部分,只看我们要学习的
其实spring在判断当前bean是byName,还是byType,就是根据beanDefinition中的autowireMode属性来判断的,这里所说的byType、byName和@Autowired注解的先根据类型注入,再根据name注入没有关系,不是同一个概念,@Autowired注解属于autowireMode为0的场景下的一个知识点
结论
这里说这个代码,只是为了举个例子,来说明,spring实际在对一个bean进行初始化的时候,是以beanDefinition中的属性信息为准的,所以这也是为什么spring提供了一些扩展机制,去修改beanDefinition属性信息、让程序员自己去注入beanDefinition,举个简单例子,比如说,我想将Test.class的autowireMode从默认值0,修改为1,那我们就可以通过实现ImportBeanDefinitionRegistrar接口,在其registerBeanDefinitions方法中,去修改Test类对应的beanDefinition中的autowireMode属性,为什么可以修改?因为registerBeanDefinitions这个方法有一个入参:BeanDefinitionRegistry,经常看源码的就知道,这个类提供了对beanDefinition进行增、删、改、查的方法,简单而言就是说,spring将root权限交给了程序员
所以:spring很强大,将一切都包装的很好,如果我们想自己去扩展spring,也可以,但是需要知道spring提供了哪些扩展点,以及这些扩展点的执行时机
本文探讨了Spring框架中的bean、beanDefinition和class之间的关系。beanDefinition是bean的描述信息,包含了如是否是primary、是否懒加载等属性。Spring通过beanDefinition来创建和初始化bean。在自动扫描过程中,class被转化为beanDefinition。Spring初始化bean时,根据beanDefinition的属性进行判断。文章还提及了beanDefinition在自动注入模型判断中的作用,并指出可以通过实现ImportBeanDefinitionRegistrar接口修改beanDefinition属性,实现对Spring的扩展。
528

被折叠的 条评论
为什么被折叠?



