执行好mergeBeanPostprocessor之后,接着我们填充属性。但是接下来还有一段代码做了一些其他操作
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 判断当前bean是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
//只保留二级缓存,不向三级缓存中存放对象
//earlySingletonObjects.put(beanName,bean);
//registeredSingletons.add(beanName);
//
// synchronized (this.singletonObjects) {
// if (!this.singletonObjects.containsKey(beanName)) {
// //实例化后的对象先添加到三级缓存中,三级缓存对应beanName的是一个lambda表达式(能够触发创建代理对象的机制)
// this.singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// this.registeredSingletons.add(beanName);
// }
// }
}
判断条件
mbd.isSingleton():是否是单例 this.allowCircularReferences:允许循环依赖 isSingletonCurrentlyInCreation(beanName):单例是否还在创建中
根据三个条件判断是否要提前暴露,因为判断条件中的三个字段都是true,所以创建好的该对象提前暴露。把该对象添加进三级缓存,二级缓存中。
logger.isTraceEnabled():检查 logger对象的 trace 级别日志是否启用。
addSingletonFactory方法,点进去看具体执行了什么
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
// 使用singletonObjects进行加锁,保证线程安全
synchronized (this.singletonObjects) {
// 如果单例对象的高速缓存【beam名称-bean实例】没有beanName的对象
if (!this.singletonObjects.containsKey(beanName)) {
// 将beanName,singletonFactory放到单例工厂的缓存【bean名称 - ObjectFactory】
this.singletonFactories.put(beanName, singletonFactory);
// 从早期单例对象的高速缓存【bean名称-bean实例】 移除beanName的相关缓存对象
this.earlySingletonObjects.remove(beanName);
// 将beanName添加已注册的单例集中
this.registeredSingletons.add(beanName);
}
}
}
锁定一级缓存,如果一级缓存中没有这个beanName的实例,将singletonFactory(实例的工厂)放入三级缓存,同时移除二级缓存的这个beanName的对象。到此执行结果如下图
继续往下走
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
//只保留二级缓存,不向三级缓存中存放对象
earlySingletonObjects.put(beanName,bean);
registeredSingletons.add(beanName);
bean对象(半成品)添加到二级缓存,单例对象被注册
接着往下走就是实例化bean的代码了。具体怎么走,我们先贴一下自己写的代码看一下这u但代码在源码中怎么走的。
public class Person {
private int id;
private String name;
private int age;
private String gender;
private Address address;
private String[] hobbies;
private List<Book> books;
private Set<Integer> sets;
private Map<String,Object> maps;
private Properties properties;
public Person(int id, String name, int age, String gender) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
System.out.println("有参构造器");
}
public Person(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
System.out.println("Age");
}
public Person(int id, String name, String gender) {
this.id = id;
this.name = name;
this.gender = gender;
System.out.println("gender");
}
public Person() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public String[] getHobbies() {
return hobbies;
}
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
public Set<Integer> getSets() {
return sets;
}
public void setSets(Set<Integer> sets) {
this.sets = sets;
}
@PostConstruct
public void init(){
System.out.println("init---person");
}
@PreDestroy
public void destroy(){
System.out.println("destroy---person");
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", address=" + address +
", hobbies=" + Arrays.toString(hobbies) +
", books=" + books +
", sets=" + sets +
", maps=" + maps +
", properties=" + properties +
'}';
}
}
public class TestPopulate {
public static void main(String[] args) {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("populateBean.xml");
ac.close();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="person1" class="com.mashibing.populateBean.Person" autowire="byName"></bean>
<bean id="person2" class="com.mashibing.populateBean.Person" autowire="byType"></bean>
<bean id="address" class="com.mashibing.populateBean.Address">
<property name="province" value="河北"></property>
<property name="city" value="邯郸"></property>
<property name="town" value="武安"></property>
</bean>
</beans>
源码中填充属性的代码
先将当前创建的半成品bean对象赋值给exposedObject,然后执行populateBean和
initializeBean,我们先看一下populateBean是怎么走的。
可以看到进去的时候先判断之前创建的包装类是否是空的,如果是空的并且有属性的话就需要抛出异常。前面的包装类被赋值了半成品对象。所以这里进不去,往下走
这里的判断条件
hasInstantiationAwareBeanPostProcessors():判断工厂是否InstanceAwareBeanPostprocessor
mbd.isSynthetic():synthetic:指的是是否是spring的内部bean,而不是用户定义的,为true。一般是指只有AOP相关的pointCut配置或者Advice配置才会将 synthetic设置为true
所以不能进入内部,接着往下走
PropertyValues:指的是bean的定义信息中封装好的属性的值,具体值如下图所示
接着看mbd.getResolvedAutowireMode():获取自动装配的类型,点进去看有哪几种类型
/**
* 没有自动装配
*/
int AUTOWIRE_NO = 0;
/**
* 按照名字自动装配
*/
int AUTOWIRE_BY_NAME = 1;
/**
* 按照类型自动装配
*/
int AUTOWIRE_BY_TYPE = 2;
/**
* 按照构造器自动装配
*/
int AUTOWIRE_CONSTRUCTOR = 3;
这里可以取到,这个值为1,说明是根据名称进行装配的
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
MutablePropertyValues
:创建一个新的 MutablePropertyValues
对象 newPvs
,这是 PropertyValues
接口的默认实现,可以对属性进行简单操作,并且支持深度复制。但是这里的代码只是初始化一个newPvs,这个新的实例包含了 pvs
的属性值,属于浅复制。如下图,就是做赋值操作,里面的数据没有太大的区别
因为我们这边是根据名称注入,走进去看看具体实现
无论是通过名称注入还是通过类型注入主要完成这两步:
pvs.add(propertyName, autowiredArgument);
方法用于将自动装配的属性和值添加到 PropertyValues
集合中
registerDependentBean(autowiredBeanName, beanName);
方法用于注册 Bean 之间的依赖关系。
①接着看一下根据名称自动装配的方法,进入autowireByName方法。思路方向大概如下
-
获取非简单属性名:
- 使用
unsatisfiedNonSimpleProperties
方法获取当前 bean 中有 setter 方法、非简单类型属性且未在PropertyValues
中配置的属性名。
- 使用
-
自动装配:
- 遍历这些属性名,检查当前 bean 工厂是否包含同名的 bean 定义或外部注册的单例实例。
- 如果存在同名 bean,将其添加到
pvs
中,并注册依赖关系。
-
日志记录:
- 记录每个属性的自动装配过程,方便调试和跟踪。
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取bw中有setter方法 && 非简单类型属性 && mbd的PropertyValues中没有该pd的属性名的 PropertyDescriptor 属性名数组
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//遍历属性名
for (String propertyName : propertyNames) {
//如果该bean工厂有propertyName的beanDefinition或外部注册的singleton实例
if (containsBean(propertyName)) {
//获取该工厂中propertyName的bean对象
Object bean = getBean(propertyName);
//将propertyName,bean添加到pvs中
pvs.add(propertyName, bean);
//注册propertyName与beanName的依赖关系
registerDependentBean(propertyName, beanName);
//打印跟踪日志
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
//打印跟踪日志
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
unsatisfiedNonSimpleProperties:获取当前 BeanWrapper
中的属性名数组 ,这些属性满足以下条件(对应这个方法中的判断条件):
- 有 setter 方法。
- 属性类型不是简单类型(即不是基础类型,如 int, long, String 等)。
- 在
mbd
的属性值集合中没有该属性名。
点进unsatisfiedNonSimpleProperties,从名字就可以猜测出这个方法是返回一个不满足要求的非简单bean属性数组。
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
//TreeSet:TreeSet底层是二叉树,可以对对象元素进行排序,但是自定义类需要实现comparable接口,重写comparaTo()方法。
Set<String> result = new TreeSet<>();
//获取mdbd的所有属性值
PropertyValues pvs = mbd.getPropertyValues();
//PropertyDescriptor:表示JavaBean类通过存储器导出一个属性,获取bw的所有属性描述对象
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
//遍历属性描述对象
for (PropertyDescriptor pd : pds) {
//如果 pd有写入属性方法 && 该pd不是被排除在依赖项检查之外 && pvs没有该pd的属性名 && pd的属性类型不是"简单值类型"
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
//将pdd的属性名添加到result中
result.add(pd.getName());
}
}
//将result装换成数组
return StringUtils.toStringArray(result);
}
PropertyValues:包装一个对象所有的PropertyValue,封装了一些基本操作用于持有一组属性值,并提供了对属性值的获取、设置和修改操作。 PropertyDescriptor:Java Bean通过一对访问器方法导出的一个属性。用于描述一个属性的元数据,包括属性名称、读写方法和属性类型等信息,它提供了对属性元数据的访问。
看一下取到的pvs和pds对应的值
接着看一下判断条件里面的
①可以看到pd.getWriteMethod():查看该属性是否有写入方法
② isExcludedFromDependencyCheck:从名称可以看出是否被排除在依赖项检查之外,点进去看一下
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
//pd的属性是CGLIB定义的属性 || 该工厂的忽略依赖类型列表中包含该pd的属性类型 || pd的属性是ignoredDependencyInterfaces里面的接口定义的方法
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}
点进isExcludedFromDependencyCheck
public static boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
//获取pd的写入属性值方法
Method wm = pd.getWriteMethod();
//如果wm为nul,就认为没有问题
if (wm == null) {
return false;
}
//如果wm的声明类的类名不包含'$$'
if (!wm.getDeclaringClass().getName().contains("$$")) {
// Not a CGLIB method so it's OK.
//如果wm的声明类的类名不包含'$$'
return false;
}
// It was declared by CGLIB, but we might still want to autowire it
// if it was actually declared by the superclass.
// 它是由CGLIB声明的,但如果它是由超类声明的,我们可能仍然想要自动装配它。
// 获取wm声明类的父类
Class<?> superclass = wm.getDeclaringClass().getSuperclass();
//如果父类没有该wm方法,就认为没有问题,否则排除
return !ClassUtils.hasMethod(superclass, wm);
}
因为判断条件wm.getDeclaringClass().getName(),获取set方法对应的Class的名称是否包括$$,执行结果为false
其他两个判断条件就不看了,三个判断条件执行的功能分别是:pd的属性是CGLIB定义的属性 || 该工厂的忽略依赖类型列表中包含该pd的属性类型 || pd的属性是ignoredDependencyInterfaces里面的接口定义的方法
这里的返回结果为false,如图
③pvs.contains(pd.getName())查看属性值中是否包含这个属性描述对象对应的名称
④BeanUtils.isSimpleProperty(pd.getPropertyType()):检查给定的类型是否表示 'simple' 属性:简单值类型还是简单值类型数组
public static boolean isSimpleProperty(Class<?> type) {
//如果 type 为null 抛出异常
Assert.notNull(type, "'type' must not be null");
// 如果type是"简单"值类型 || (type是数组 & type的元素类型是否"简单"值类型) 就为ture;否则为false
return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
}
点进isSimpleValueType,有以下这些简单类型
public static boolean isSimpleValueType(Class<?> type) {
return (Void.class != type && void.class != type &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
Temporal.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}
以这四个判断条件,遍历属性描述对象,当满足上述四个判断条件的属性就是引用类型,则加入result(在这里做的操作其实就是将引用类型和基本数据类型区分开来)
可以看到这里添加进result的数据都是非简单数据类型
返回非简单类型的数组后,要对这个数组进行处理,看autowireByName方法接下来怎么走,再贴一下这个方法
接着就是遍历这些属性值,首先进去就要执行containsBean方法,点进去
@Override
public boolean containsBean(String name) {
// 获取name最终的规范名称【最终别名】
String beanName = transformedBeanName(name);
// 如果beanName存在于singletonObjects【单例对象的高速缓存Map集合】中,
// 或者从beanDefinitionMap【Bean定义对象映射】中存在该beanName的BeanDefinition对象
if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
}
// Not found -> check parent.
// 获取父工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果父工厂不为null 则递归形式查询该name是否存在于父工厂,并返回执行结果;为null时直接返回false
// 因为经过上面步骤,已经确定当前工厂不存在该bean的BeanDefinition对象以及singleton实例
return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}
看一下判断条件containsBeanDefinition(beanName)的执行结果
因为beanDefinition中有这个beanName对应的定义信息, 所以可以进入,看一下里面的BeanFactoryUtils.isFactoryDereference(name),可以看到 这个方法主要判断传进去的名称是否以&开头。
public static boolean isFactoryDereference(@Nullable String name) {
// 如果有传入bean名且bean名是以'&'开头,则返回true,表示是BeanFactory的解引用,否则
// 返回false,表示不是BeanFactory的解引用
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
并且这个beanName没有以&开头,所以执行containBean方法返回true。所以在autowireByName
方法中就可以进入,对于address对象,之前还没有创建过,所以在进入getBean之后要创建对象address,遵守创建对象的那套流程,这里就不做具体阐述了。
getBean(address)执行完成之后会返回一个完整的address放到一级缓存中,然后再执行pvs.add将address对象注入到到Person对象中。具体结果如上图所示。
②根据类型自动注入
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取工厂的自定义类型转换器
TypeConverter converter = getCustomTypeConverter();
//如果没有配置自定义类型转换器
if (converter == null) {
//使用bw作为类型转换器
converter = bw;
}
//存放所有候选Bean名的集合
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//获取bw中有setter方法 && 非简单类型属性 && mbd的PropertyValues中没有该pd的属性名的 PropertyDescriptor 属性名数组
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
//遍历属性名数组
for (String propertyName : propertyNames) {
try {
//PropertyDescriptor:表示JavaBean类通过存储器导出一个属性
//从bw中获取propertyName对应的PropertyDescriptor
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
// 不要尝试按类型自动装配对象:永远是有意义的,即使它在技术上是一个不满意,复杂属性
//如果pd的属性值类型不是 Object
if (Object.class != pd.getPropertyType()) {
//获取pd属性的Setter方法的方法参数包装对象
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
//判断bean对象是否是PriorityOrder实例,如果不是就允许急于初始化来进行类型匹配。
//eager为true时会导致初始化lazy-init单例和由FactoryBeans(或带有"factory-bean"引用的工厂方法)创建 的对象以进行类型检查
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
//AutowireByTypeDependencyDescriptor:根据类型依赖自动注入的描述符,重写了 getDependencyName() 方法,使其永远返回null
//将 methodParam 封装包装成AutowireByTypeDependencyDescriptor对象
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//根据据desc的依赖类型解析出与descriptor所包装的对象匹配的候选Bean对象
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
//如果autowiredArgument不为null
if (autowiredArgument != null) {
//将proeprtyName.autowireArgument作为键值添加到pvs中
pvs.add(propertyName, autowiredArgument);
}
//遍历所有候选Bean名集合
for (String autowiredBeanName : autowiredBeanNames) {
//注册beanName与dependentBeanNamed的依赖关系
registerDependentBean(autowiredBeanName, beanName);
//打印跟踪日志
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
//将候选Bean名集合清空
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
//捕捉自动装配时抛出的Bean异常,重新抛出 不满足依赖异常
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
看这个方法中的具体实现
TypeConverter converter = getCustomTypeConverter();
// 如果没有配置自定义类型转换器
if (converter == null) {
// 使用 bw 作为类型转换器
converter = bw;
}
-
类型转换器初始化:
- 获取自定义类型转换器(如果存在)。如果没有配置自定义类型转换器,就使用
BeanWrapper
作为类型转换器。
- 获取自定义类型转换器(如果存在)。如果没有配置自定义类型转换器,就使用
-
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
-
获取非简单类型属性名:
- 使用
unsatisfiedNonSimpleProperties
方法获取当前BeanWrapper
中的属性名数组,这些属性满足以下条件:- 有 setter 方法。
- 属性类型不是简单类型(即不是基础类型,如 int, long, String 等)。
- 在
mbd
的属性值集合中没有该属性名。
- 使用
-
遍历属性名:
- 遍历从
unsatisfiedNonSimpleProperties
返回的属性名数组。
- 遍历从
-
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
-
获取属性描述符:
- 对于每个属性名,获取对应的
PropertyDescriptor
。
- 对于每个属性名,获取对应的
-
忽略 Object 类型:
- 如果属性类型是
Object
,跳过自动装配(因为按类型自动装配Object
类型没有意义)。
- 如果属性类型是
-
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
-
获取方法参数:
- 获取
PropertyDescriptor
对应的 setter 方法的参数。
- 获取
-
急于初始化类型匹配:
- 判断当前 bean 对象是否实现
PriorityOrdered
接口。如果不是,则允许急于初始化来进行类型匹配。
- 判断当前 bean 对象是否实现
-
创建依赖描述符:
- 将方法参数封装成
AutowireByTypeDependencyDescriptor
对象。这个描述符用于描述依赖项。
- 将方法参数封装成
-
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
-
解析依赖:
- 使用
resolveDependency
方法根据描述符解析出与其匹配的候选 bean 对象。
- 使用
-
pvs.add(propertyName, autowiredArgument);
-
添加属性值:
- 如果解析出的依赖对象不为 null,将属性名和依赖对象添加到
pvs
中。
- 如果解析出的依赖对象不为 null,将属性名和依赖对象添加到
-
registerDependentBean(autowiredBeanName, beanName);
-
注册依赖关系:
- 遍历所有候选 bean 名,注册依赖关系。
-
清空候选 bean 名集合:
- 清空候选 bean 名集合,以便下一次使用。
-
异常处理:
- 捕获自动装配过程中抛出的
BeansException
,并重新抛出为UnsatisfiedDependencyException
,提供详细的错误信息。
- 捕获自动装配过程中抛出的
点进resolveDependency
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 获取工厂的参数名发现器,设置到descriptor中。使得descriptor初始化基础方法参数的参数名发现。此时,该方法实际上
// 并没有尝试检索参数名称;它仅允许发现再应用程序调用getDependencyName时发生
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 如果descriptor的依赖类型为Optional类
if (Optional.class == descriptor.getDependencyType()) {
//创建Optional类型的符合descriptor要求的候选Bean对象
return createOptionalDependency(descriptor, requestingBeanName);
}
// 是对象工厂类型或者对象提供者
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
// DependencyObjectProvider:依赖对象提供者,用于延迟解析依赖项
// 新建一个DependencyObjectProvider的实例
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
// javaxInjectProviderClass有可能导致空指针,不过一般情况下,我们引用Spirng包的时候都有引入该类以防止空旨在
// 如果依赖类型是javax.inject.Provider类。
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
// Jse330Provider:javax.inject.Provider实现类.与DependencyObjectProvoid作用一样,也是用于延迟解析依赖
// 项,但它是使用javax.inject.Provider作为依赖 对象,以减少与Springd耦合
// 新建一个专门用于构建javax.inject.Provider对象的工厂来构建创建Jse330Provider对象
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 尝试获取延迟加载代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
// 如果result为null,即表示现在需要得到候选Bean对象
if (result == null) {
// 解析出与descriptor所包装的对象匹配的候选Bean对象
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
// 将与descriptor所包装的对象匹配的候选Bean对象【result】返回出去
return result;
}
}
具体分析下代码
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
使用 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()) 初始化参数名发现器,以备可能的参数名发现需求。
if (Optional.class == descriptor.getDependencyType()) {
// 创建一个符合 descriptor 要求的 Optional 类型的依赖对象
return createOptionalDependency(descriptor, requestingBeanName);
}
// 如果依赖类型为 ObjectFactory 或 ObjectProvider
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
// 创建一个依赖对象提供者(用于延迟解析依赖项)
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
// 如果依赖类型为 javax.inject.Provider 类
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
// 创建一个 JSR-330 Provider 对象的工厂来创建依赖对象
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
对于 Optional
、ObjectFactory
、ObjectProvider
和 javax.inject.Provider
类型的依赖,采取特定的处理方式,例如创建特定的对象或提供者。
else {
// 通过自动装配的候选解析器获取必要时的延迟加载代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
// 如果代理对象为空,则尝试解析依赖并返回
if (result == null) {
// 执行实际的依赖解析过程
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
// 返回解析出的依赖对象
return result;
}
这段代码的核心作用是通过自动装配候选解析器,判断是否有必要使用延迟加载的代理对象来优化依赖项的初始化。如果有必要,则返回一个代理对象,否则返回 null,表示需要立即解析依赖项。通过这种机制,Spring 能够在适当的场景下优化依赖项的初始化过程,提高应用程序的性能和资源利用效率。
因为获取到的依赖类型是address,所以前面几个if都走不进去,直接进入else.
执行getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary,从名称可以看出这里是一些关于延迟加载的东西。(尝试获取延迟加载代理对象)
我们这边没有设置有关延迟的东西,所以可以看到尝试执行前面一个方法的时候获取的值就是空的。所以进入doResolveDependency方法
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//。。。。
//尝试针对desciptor所包装的对象类型是[stream,数组,Collection类型且对象类型是接口,Map]的情况,进行解析与依赖类型匹配的候选Bean对象
//针对desciptor所包装的对象类型是[stream,数组,Collection类型且对象类型是接口,Map]的情况,进行解析与依赖类型匹配的 候选Bean对象,
// 并将其封装成相应的依赖类型对象
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
//如果multpleBeans不为null
if (multipleBeans != null) {
//将multipleBeans返回出去
return multipleBeans;
}
//尝试与type匹配的唯一候选bean对象
//查找与type匹配的候选bean对象,构建成Map,key=bean名,val=Bean对象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//...
//定义用于存储唯一的候选Bean名变量
String autowiredBeanName;
//定义用于存储唯一的候选Bean对象变量
Object instanceCandidate;
if{
//...}
else {
// We have exactly one match.
//这个时候matchingBeans不会没有元素的,因为前面已经检查了
//获取machingBeans唯一的元素
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
//让autowireBeanName引用该元素的候选bean名
autowiredBeanName = entry.getKey();
//让instanceCandidate引用该元素的候选bean对象
instanceCandidate = entry.getValue();
}
//如果候选bean名不为null,
if (autowiredBeanNames != null) {
//将autowiredBeanName添加到autowiredBeanNames中,又添加一次
autowiredBeanNames.add(autowiredBeanName);
}
//如果instanceCandidate是Class实例
if (instanceCandidate instanceof Class) {
//让instanceCandidate引用 descriptor对autowiredBeanName解析为该工厂的Bean实例
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
//定义一个result变量,用于存储最佳候选Bean对象
//...
Object result = instanceCandidate;
//返回最佳候选Bean对象【result】
return result;
}
//...
这个方法的代码太多,只贴了关键部分,点进resolveMultipleBeans
resolveMultipleBeans:
解析给定依赖描述符 descriptor
所描述的多个候选 bean 对象。
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
// 获取包装的参数/字段的声明的(非通用)类型
Class<?> type = descriptor.getDependencyType();
// 如果描述符是Stream依赖项描述符
if (descriptor instanceof StreamDependencyDescriptor) {
//.....
}
// 如果依赖类型是数组类型
else if (type.isArray()) {
//...
}
// 如果依赖类型属于Collection类型且依赖类型是否接口
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
//...
}
// 如果依赖类型是Map类型
else if (Map.class == type) {
//...
}
else {
// 返回null,表示获取不到候选bean对象
return null;
}
}
可以看到这个方法就是针对desciptor所包装的对象类型是[stream,数组,Collection类型且对象类型是接口,Map]的情况,进行解析是否是这些集合类型是与之匹配的候选Bean对象。我们这里不是。
接着往下走,findAutowireCandidates方法获取与type匹配的bean对象,返回对应的bean:address
到这里我们把autoBytype的resolveDependency执行完毕
进入到下面的registerDependentBean
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取name的最终别名或者是全类名
String canonicalName = canonicalName(beanName);
// 使用存储bean名到该bean名所要依赖的bean名的Map作为锁,保证线程安全
synchronized (this.dependentBeanMap) {
// 获取canonicalName对应的用于存储依赖Bean名的Set集合,如果没有就创建一个LinkedHashSet,并与canonicalName绑定到dependentBeans中
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
// 如果dependentBeans已经添加过来了dependentBeanName,就结束该方法,不执行后面操作。
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
//使用Bean依赖关系Map作为锁,保证线程安全
synchronized (this.dependenciesForBeanMap) {
//添加dependendtBeanName依赖于cannoicalName的映射关系到 存储 bean名到依赖于该bean名的bean名 的Map中
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
执行完毕
可以看到根据类型注入,只要是set类型,都往里面设置。
继续往下走
我们再看一下平常经常用到的引用属性注入例子,先贴一下代码
@Controller
public class PersonController {
@Autowired
private PersonService personService;
}
@Service
public class PersonService {
@Autowired
private PersonDao personDao;
}
@Repository
public class PersonDao {
}
继续走到populate方法,大概装配PersonController的时候我们点进去
对于没有执行到的代码直接删除,贴了部分代码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 如果beanWrapper为空
if (bw == null) {
//...
}
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//...
}
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
//...
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
CommonAnnoationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor
if (hasInstAwareBpps) {
//如果pvs为null
if (pvs == null) {
//尝试获取mbd的PropertyValues
pvs = mbd.getPropertyValues();
}
//遍历工厂内的所有后置处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果 bp 是 InstantiationAwareBeanPostProcessor 的实例
if (bp instanceof InstantiationAwareBeanPostProcessor) {
//将bp 强转成 InstantiationAwareBeanPostProcessor 对象
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//postProcessProperties:在工厂将给定的属性值应用到给定Bean之前,对它们进行后处理,不需要任何属性扫描符。该回调方法在未来的版本会被删掉。
// -- 取而代之的是 postProcessPropertyValues 回调方法。
// 让ibp对pvs增加对bw的Bean对象的propertyValue,或编辑pvs的proertyValue
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
//如果pvs为null
if (pvsToUse == null) {
//如果filteredPds为null
if (filteredPds == null) {
//mbd.allowCaching:是否允许缓存,默认时允许的。缓存除了可以提高效率以外,还可以保证在并发的情况下,返回的PropertyDesciptor[]永远都是同一份
//从bw提取一组经过筛选的PropertyDesciptor,排除忽略的依赖项或忽略项上的定义的属性
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
//postProcessPropertyValues:一般进行检查是否所有依赖项都满足,例如基于"Require"注释在 bean属性 setter,
// -- 替换要应用的属性值,通常是通过基于原始的PropertyValues创建一个新的MutablePropertyValue实例, 添加或删除特定的值
// -- 返回的PropertyValues 将应用于bw包装的bean实例 的实际属性值(添加PropertyValues实例到pvs 或者 设置为null以跳过属性填充)
//回到ipd的postProcessPropertyValues方法
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
//如果pvsToUse为null,将终止该方法精致,以跳过属性填充
if (pvsToUse == null) {
return;
}
}
//让pvs引用pvsToUse
pvs = pvsToUse;
}
}
}
//如果需要依赖检查
if (needsDepCheck) {
//...
}
//如果pvs不为null
if (pvs != null) {
//应用给定的属性值,解决任何在这个bean工厂运行时其他bean的引用。必须使用深拷贝,所以我们 不会永久地修改这个属性
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
因为我们执行 hasInstantiationAwareBeanPostProcessors()返回结果为true。所以属性值为true,进入if里面,当执行到AutowiredAnnotationBeanPostprocessor时点入postProcessProperties
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 从缓存中取出这个bean对应的依赖注入的元信息~
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 进行属性注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
从代码中可以看到先执行获取元信息的操作,然后再将对应的pvs属性值注入到元信息中。我们分别点进findAutowiringMetadata和inject方法
看一下图中的执行流程,可以看到直接从缓存中获取并返回
可以看到返回的元信息中已经表明了目标对象PersonController中注入personService对象。接着我们执行metadata.inject(bean, beanName, pvs);将引用属性注入到targetClass中。看一下inject方法怎么走的
从图中可以看出便利属性,执行inject方法,点入这方法
可以看到这里同样走resolveDependency获取依赖的value值,以及走registerDependentBeans注册依赖bean。点进这两个方法看看具体怎么走
点进去
点进去
判断条件
isSelfReference:判断当前遍历到的候选 Bean 名称是否与目标 Bean 名称(beanName)相同isAutowireCandidate(candidate, descriptor)
:调用 isAutowireCandidate
方法,判断候选 Bean 是否符合自动装配的条件。这个方法用于判断候选 Bean 是否可以被自动注入。
执行完findAutowireCandidates,继续往下走
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
可以看到执行resolveCandidate,获取personService对象,因为之前还没有创建这个对象,所以走getBean-->doGetBean-->getSingleton-->createBean-->doCreateBean-->createBeanInstance-->populateBean-->(resolveDependency,registerDependentBeans)这个流程创建PersonService对象。
整个populate的过程就是PersonController在populate的时候创建PersonService,PersonService在populate的时候创建PersonDao.
把这三个对象创建的流程走完,走到注册依赖bean,方法的执行流程如下图所示,点进去
看一下里面的注册操作
这里可以举一个例子表明这里的注册操作。A对象中注入B,C对象,那么
dependentBeanMap:{"beanA" -> ["beanB", "beanC"]}
dependenciesForBeanMap:{"beanB" -> ["beanA"]},{"beanC" -> ["beanA"]}
...Resolver/handler:...处理器
...registory:...增删改查