Spring源码学习笔记@AutoWire的propertyValues属性注入分析
1概述
本文基于Spring Framework版本5.0.0(最新版本5.3.4,SringBoot最新版本2.4.2。(参考文档: https://docs.spring.io/spring-boot/docs/current/api/)
1.1Spring各个版本区别
GA:General Availability,正式发布的版本,官方推荐使用此版本。在国外都是用GA来说明release版本的。
PRE: 预览版,内部测试f版. 主要是给开发人员和测试人员测试和找BUG用的,不建议使用;
SNAPSHOT: 快照版,可以稳定使用,且仍在继续改进版本。
1.2 @AutoWire
1.2.1注入类型
public interface AutowireCapableBeanFactory extends BeanFactory {
/**
* 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;
2代码示例
2.1pom文件配置
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--2.spring对web的支持,依赖 spring-webmvc-->
<!--此时jar包会自动下载(spring-context、spring-web、spring-webmvc)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--2.2.spring dao层依赖(jdbc 和 tx)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--2.3.spring test相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
2.2定义普通的pojo类
package com.kikop.myspring1.model;
/**
* @author kikop
* @version 1.0
* @project Name: myspringdemo
* @file Name: MyFamily
* @desc 每个家庭都对应房子,通过后置处理器注入
* @date 2021/2/14
* @time 10:50
* @by IDE: IntelliJ IDEA
*/
public class MyFamily {
private String name;
private MyHouse myHouse;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyHouse getMyHouse() {
return myHouse;
}
// 通过setter方法注入
public void setMyHouse(MyHouse myHouse) {
System.out.println("exec setMyHouse method");
this.myHouse = myHouse;
}
public MyFamily(String name) {
this.name = name;
}
}
package com.kikop.myspring1.model;
/**
* @author kikop
* @version 1.0
* @project Name: myspringdemo
* @file Name: MyHouse
* @desc 通过setter方法注入
* @date 2021/2/14
* @time 10:50
* @by IDE: IntelliJ IDEA
*/
public class MyHouse {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.3定义配置类
package com.kikop.myspring4.config;
import com.kikop.myspring1.model.MyHouse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author kikop
* @version 1.0
* @project Name: myspringdemo
* @file Name: AppConfig4
* @desc 可以实现基于Java的配置类加载Spring的应用上下文
* @date 2021/2/14
* @time 10:50
* @by IDE: IntelliJ IDEA
*/
// @Configuration:可理解为
// 1.传统用spring的时候xml里面的<beans>标签
// 2.特别是类中存在Beans依赖时,从而确保对象被构造一次
@Configuration
public class AppConfig4 {
@Bean
MyHouse myHouse() {
MyHouse myHouse = new MyHouse();
myHouse.setName("dfhy");
return myHouse;
}
}
2.4测试
package com.kikop.myspring4;
import com.kikop.myspring1.model.MyFamily;
import com.kikop.myspring4.config.AppConfig4;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.springframework.beans.factory.support.AbstractBeanDefinition.AUTOWIRE_BY_NAME;
import static org.springframework.beans.factory.support.AbstractBeanDefinition.AUTOWIRE_BY_TYPE;
/**
* @author kikop
* @version 1.0
* @project Name: myspringdemo
* @file Name: MySpringTest
* @desc 可以实现基于Java的配置类加载Spring的应用上下文
* @date 2021/2/14
* @time 10:50
* @by IDE: IntelliJ IDEA
*/
public class MySpringTest {
private static void registerBeanDefBeforeIocRefresh() {
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(AppConfig4.class);
// GenericBeanDefinition是其子类
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(MyFamily.class);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("kikopF"); // familyName
// 通过类型自动setteer注入 MyHouse属性,否则 MyFamily属性不会被填充,
// 执行时机:finishBeanFactoryInitialization-->populateBean(beanName, mbd, instanceWrapper)
beanDefinition.setAutowireMode(AUTOWIRE_BY_TYPE);
// beanDefinition.setAutowireMode(AUTOWIRE_BY_NAME);
annotationConfigApplicationContext.registerBeanDefinition("myFamily", beanDefinition);
annotationConfigApplicationContext.refresh();
MyFamily myFamily =
(MyFamily) annotationConfigApplicationContext.getBean("myFamily");
System.out.println(myFamily);
annotationConfigApplicationContext.close();
}
public static void main(String[] args) {
registerBeanDefBeforeIocRefresh();
}
}
2.5输出
3AUTOWIRE源码解读
3.1总结
具体实现如下:
// org\springframework\context\support\AbstractApplicationContext.java
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 这里我们开始进行单例对象的创建
beanFactory.preInstantiateSingletons();
}
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.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.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
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 {
// 获取容器中的bean,不存在则创建
getBean(beanName);
}
}
}
// org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java
//---------------------------------------------------------------------
// Implementation of relevant AbstractBeanFactory template methods
//---------------------------------------------------------------------
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 这里,开始进行真正的bean创建
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw BeanWrapper with bean instance
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 1.关键的地方来了
// 先取出原有 RootBeanDefinition的属性值,用于后面合并
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
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.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 2.1.这里我们根据RootBeanDefinition的autoWireMode:名称
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 2.2.这里我们根据RootBeanDefinition的autoWireMode:类型
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 3.当前创建的beanName,当前bean的 RootBeanDefinition,bw:BeanWrapper,需要注入的属性值。
applyPropertyValues(beanName, mbd, bw, pvs);
}
到这里,我们可以看看当前BeanDef的数值如下:

// org\springframework\beans\factory\support\AbstractAutowireCapableBeanFactory.java
/**
* Apply the given property values, resolving any runtime references
* to other beans in this bean factory. Must use deep copy, so we
* don't permanently modify this property.
* @param beanName the bean name passed for better exception information
* @param mbd the merged bean definition
* @param bw the BeanWrapper wrapping the target object
* @param pvs the new property values
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {
return;
}
// Set our (possibly massaged) deep copy.
try {
// 这里,我们即将进行set属性的注入,本质是通过Java反射完成。
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
网友评论