「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战」
Autowired注解(不带指定类型)
这部分就对应这里了:
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
这里:
- autowired注解,是通过AutowiredAnnotationBeanPP实现的。
- resource注解,是通过CommonAnnotationBeanPP实现的。
这里就看看autowired的:
AutowiredAnnotationBeanPP
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {}
-
SmartInstantiationAwareBeanPostProcessor接口简单来说就是更强大的InstantiationAwareBeanPostProcessor:
- 推断构造方法
- 解决循环依赖
- 处理属性
注入之前
同时,这个PP也继承了MergedBeanDefinitionPostProcessor,也就是说会在bean属性注入之前被调用一次
postProcessMergedBeanDefinition方法:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
这里会将bean中需要注入的值(注入点,被autowired修饰的方法或者属性)先找出来并做缓存:
- 查找注入点
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
- 构造注入点相关信息
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
//在找注入点之前,会判断:当前的类是否是候选类【1】
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
//找字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//查找是否有对应的注解(autowired,value,inject)
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
//这里需要注意:如果是static的字段就直接return了
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
//针对autowired(require = true),默认就是true
//这里就代表是否一定要有这个bean,没有则报错;如果是false,则不会
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//找方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
//同样的跳过static
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
//如果方法不需要参数,一样会当作注入点
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
elements.addAll(0, currElements);
//这里会再往上查找父类的
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
//最后再把字段和方法,封装并返回
return InjectionMetadata.forElements(elements, clazz);
}
-
什么时候类不需要有注入点?
- 就是上面所说的基础类型
-
为什么不给static赋值?
- 如果是原型bean,那么对应的多个实例中这部分的属性会导致同一个bean的同一个static属性,在不同的时候获取到的是不同的,会造成混乱
- 如果实在是要为static属性赋值,可以通过set方法里为static赋值,并设置为单例bean来绕过。
-
桥接方法 bridgedMethod:
- 这部分和继承实现相关
- 如果接口是泛型,并且实现类指定了类型,那么编译后会出现两个同样的set方法但类型不同(一个是指定的类型,一个是Object,这里的Object被称为桥接方法)
- 因此这里会找一下子类上被桥接的方法,如果是桥接方法就不会当作注入点
注入过程调用
上面做完了,在Spring中后续会调用这个方法:
@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;
}
在这里就是会给注入点来进行注入。
对应代码如下:
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
//值的inject,autowiredFieldMetadata
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
value = resolveFieldValue(field, bean, beanName);
}
}
else {
value = resolveFieldValue(field, bean, beanName);
}
//底层还是通过反射来取值的
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
//方法的inject,autowiredMethodMetadata
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//这里就是判断是否已经手动给属性赋值了,但只在方法注入的时候判断了,并没有在属性注入的时候判断
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
try {
arguments = resolveCachedArguments(beanName);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
arguments = resolveMethodArguments(method, bean, beanName);
}
}
else {
arguments = resolveMethodArguments(method, bean, beanName);
}
//一样是反射
if (arguments != null) {
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
- 如果在BD中赋值,那么虽然字段部分的autowired不会忽略,但BD中的值会在autowired之后再执行,因此BD中的赋值会在后续中再盖上去。
这里的关键是resolveFieldValue和resolveMethodArguments,实际上调用的是beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter)