所有文章已迁移至csdn,csdn个人主页https://blog.csdn.net/chaitoudaren
spring属性注入分4种:
- 不开启自动注入,即xml自己配置property
- 通过名称自动注入
- 通过类型自动注入
- @Autowire自动注入
本篇我们将介绍前三种,@Autowire应该是百分之99的开发者选择的的注入方式,它通过属性填充中的后置处理器完成,因此本篇有涉及后置处理器的不用太纠结,将单独一片详解:spring源码日期16: @Autowired实现原理
下方代码,本篇只关心第4点属性填充
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
...
try {
//
/**
* 4. 填充属性
* 如果@Autowired注解属性,则在上方完成解析后,在这里完成注入
*
* @Autowired
* private Inner inner;
*/
populateBean(beanName, mbd, instanceWrapper);
// 5. 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
...
}
属性填充
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 如果BeanWrapper对象为null
if (bw == null) {
if (mbd.hasPropertyValues()) {
// 有属性但是没对象,那往哪里注入...直接抛异常了
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
// 没有属性就直接返回
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 1. 实例化后的后置操作
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
// 实例化后置处理器可以发出终止填充的命令,这点比较特别
return;
}
}
}
}
// 2. 获取属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 3. 根据注入方式的不同可分为 通过 ①名称注入、②类型注入、③不自动注入
/**
* ①按名称注入,则pvs在步骤2时会获取到配置文件中配置注入的属性,同时在autowireByName又会进一步通过名称添加补充
* ②按名称注入,则pvs在步骤2时会获取到配置文件中配置注入的属性,同时在autowireByType又会进一步通过类型添加补充
* ③不开启自动注入,则在步骤2 pvs就可以获取到配置文件中注入的属性
*/
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
// ①通过名称自动注入
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// ②通过类型自动注入
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 判断所有实例化后置处理器是否都已经初始化完成
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 依赖检测
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
/**
* 4. 属性填充的后置处理器
* @Autowired
* private Inner inner;
* 在这里使用AutowiredAnnotationBeanPostProcessor进行注入
*/
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// @Autowired正是在这里调用后置处理器对属性进行注入
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 对所有需要检测的属性进行后置处理
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
// 5. 将属性应用到bean中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
- 实例化后置处理
- 获取属性值
这边获取到的pvs是从配置文件中获取的,代码如下,xml配置文件中property标签仅包含b1,所以pvs仅仅会获取到b1,如果没有下一步的代码将不会注入b2(这点很容易被忽视,一定引起重视)
public Class A {
private B1 b1;
private B2 b2;
// getter&&setter
}
public Class B1 {}
public Class B2 {}
<?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"
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"
default-autowire="byName"
>
<bean id="a" class="autowire.A">
<property name="b1" ref="b1"/>
</bean>
<bean id="b1" class="B1"/>
<bean id="b2" class="B2"/>
</beans>
- 自动注入(其实这里只是获取待注入属性,并未开始实际的注入操作)
还是上方代码,注意一定要加上default-autowire="byName"这句,这句指开启按名称注入,否则spring默认不开启自动注入。开启后,spring将通过Class A类中的属性,按名称b2通过getBean("b2")的方式进行查找,并将它添加到pvs中,至此属性b1, b2才都被成功添加到pvs中,等待注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取pvs以外的其他属性,该属性必须有setter方法
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 直接通过属性名获取bean,并假如到pvs中
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
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");
}
}
}
}
- 属性填充的后置处理器,@Autowire正是在这里注入的,我们将单独一章详解:spring源码日期16: @Autowired实现原理
- 将属性注入到bean中
代码很大一部分工作用在了属性转换上,例如property传入String类型而实际属性则为int类型,当然这是最简单的一种。而我们最关心的注入操作则发生在第6步,具体代码很长就不详细分析了,但是最核心的操作则是通过反射获取到对应属性field,然后调用field.set(bean, property);实现对bean属性的赋值
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 1. pvs为空就没得注入了
if (pvs.isEmpty()) {
return;
}
// 2. 权限管理器
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
//MutablePropertyValues是PropertyValues接口的默认实现类
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
// 3. 获取bean的属性集合
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
// pvs都需要被转换成对应的类型才可以应用到beanwapper中
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
// 如果pvs已经转换过,则直接设置属性值无需再次转换
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
// 否则获取原始PropertyValue集合
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
// 4. 获取类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
// 5. 通过深度拷贝,解析值引用
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
// 循环转换PropertyValues
for (PropertyValue pv : original) {
// 已经转换过,则直接加入deepCopy
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
// 属性名
String propertyName = pv.getName();
// 属性值
Object originalValue = pv.getValue();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
// 解析原始属性值
// 当注入集合属性时,如果指定了value-type,如value-type="java.lang.String",那么resolveValueIfNecessary会执行类型的转换操作
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
// isWritableProperty判断属性是否可写,isNestedOrIndexedProperty判断是否索引属性或者嵌套属性
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
// 是否转换
if (convertible) {
// 类型转换
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
// 缓存已经转换过的值,避免再次转换。这取决于convertForProperty是否真正对属性进行了转换
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
// 6. 设置属性值,实质就是通过反射调用对属性进行赋值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
网友评论