我们大家都知道,Spring容器会管理bean,而 不需要开发者自己手动注入,从而达到了解耦的目的。我们经常使用注解@Autowired实现spring的自动注入,那么@Autowired能够实现自动注入的原理是什么样的呢?今天我们就来通过源码看下具体的实现方式。
1. 注解本身如何在代码中起作用的
首先大家要知道,注解本身本身并没有什么逻辑,把注解放在类上或者属性上,只能说明这个类或者这个属性上有这样一个名叫xxx的注解。就像是猪肉,国标的猪肉会给猪肉上边盖一个章,而这个章只是一个标记,而这个章并没有改变猪肉本身。但是我们的分拣员看到有章的猪肉,就会把该猪肉分发到正规的渠道,而没有章的猪肉就做其他处理。我们的注解其实和章是一个概念,只是起到了标记的作用,而真正起作用的是注解解析器,而注解解析器就好比是分拣员,会对有该注解的类做相应的逻辑处理。
2. @Autowired的注解解析器
这里就不卖关子了,@Autowired的注解解析器是AutowiredAnnotationBeanPostProcessor。该类的继承类图如下:
通过继承类图可以看到,AutowiredAnnotationBeanPostProcessor类间接实现了InstantiationAwareBeanPostProcessor,而InstantiationAwareBeanPostProcessor又实现了BeanPostProcessor。
BeanPostProcessor接口,如果对spring有一定了解的同学一定对这个接口不陌生,这个接口是Spring为开发者提供的扩展点,BeanPostProcessor有两个方法,postProcessBeforeInitialization和postProcessAfterInitialization,分别在bean初始化前执行postProcessBeforeInitialization发放和初始化后执行postProcessAfterInitialization方法。那InstantiationAwareBeanPostProcessor又有什么用处呢?
InstantiationAwareBeanPostProcessor接口有postProcessBeforeInstantiation、postProcessAfterInstantiation和postProcessProperties三个方法。注意,不要把前两个方法跟BeanPostProcessor的两个方法搞混淆了,前者的方法名是以Instantiation结尾,而后者的方法名是以Initialization结尾(之前我就给看成一个了)。本篇文章重点关注的postProcessProperties方法。
3. bean创建
说到依赖注入,当然要先说下bean创建了,要不然没有bean的创建,哪来的依赖注入呢?
因为bean创建不是本篇文章的重点,所以简要说下。
这里引用一篇别人的文档解释说明一下spring启动和bean创建的过程:
https://www.jianshu.com/p/927f24ceadfa
spring中绝大多数的bean都要通过如下doGetBean的代码进行创建
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
代码中有这样一段代码
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
其中,initializeBean方法是启动bean的初始化方法,而populateBean方法是给对象中的属性赋值,可以看出来,给属性赋值是要早于bean的初始化的(注意,初始化不等于实例化,初始化是bean声明周期的一个阶段,实例化只是调用了class的构造方法,相当于new )。
这篇文章主要关注属性赋值,所以我们看populateBean方法的代码:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
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.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
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();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
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) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
这里边有这样一段代码:
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
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;
}
}
这段代码的意思就是首先获取到spring中所有实现了 BeanPostProcessor接口的类,并循环逐个处理,如果某个BeanPostProcessor实现类又实现了InstantiationAwareBeanPostProcessor,则调用其postProcessProperties方法,这里就是调用@Autowired的注解解析器AutowiredAnnotationBeanPostProcessor中的postProcessProperties方法,这个方法的主要目的就是对属性进行注入。
代码如下:
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
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;
}
这个方法中使用了两个方法,一个是findAutowiringMetadata,另一个是metadata.inject(bean, beanName, pvs)。其中,前者就是通过反射机制找到该对象所有标注了@Autowired注解的属性或方法等,并以InjectionMetadata对象返回,后者就是通过metadata对象对相关属性进行属性注入。
当然,整个过程还是比较复杂的,比如注入的对象还没有生成、存在循环依赖等问题,spring是很强大、很复杂的系统,我们只能每一篇文章梳理某一个点。
这里引用另外一位作者的博客https://blog.csdn.net/topdeveloperr/article/details/87971446?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task,觉得写得好不错,两篇文章可以结合一起 看哦。
学海无涯,让我们一起加油!