Spring依赖注入@Autowired深层原理、源码级分析
前言
关于Spring IOC的依赖注入(DI机制),之前虽有过分析,但总感觉一直落了一块:对@Autowired注解元数据的解析部分。
解析@Resource注解的不是这个类,而是CommonAnnotationBeanPostProcessor,但本文只会以AutowiredAnnotationBeanPostProcessor为例做深入分析
getBean()时,进行bean对象的创建和bean依赖注入,跟xml方式类似,只是对于依赖注入@Autowired处理依赖有区别。
解析注解元信息阶段
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
protected final Log logger = LogFactory.getLog(getClass());
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
private String requiredParameterName = "required";
private boolean requiredParameterValue = true;
private int order = Ordered.LOWEST_PRECEDENCE - 2;
@Nullable
private ConfigurableListableBeanFactory beanFactory;
private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
// 方法注入、字段filed注入 本文的重中之重
// 此处InjectionMetadata这个类非常重要,到了此处@Autowired注解含义已经没有了,完全被准备成这个元数据了 所以方便我们自定义注解的支持~~~优秀
// InjectionMetadata持有targetClass、Collection<InjectedElement> injectedElements等两个重要属性
// 其中InjectedElement这个抽象类最重要的两个实现为:AutowiredFieldElement和AutowiredMethodElement
private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* if available.
*/
// 这是它唯一构造函数 默认支持下面三种租借(当然@Inject需要额外导包)
// 请注意:此处@Value注解也是被依赖注入解析的~~~~~~~~
// 当然如果你需要支持到你的自定义注解,你还可以调用下面的set方法添加。。。
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
/**
* Set the 'autowired' annotation type, to be used on constructors, fields,
* setter methods, and arbitrary config methods.
* <p>The default autowired annotation types are the Spring-provided
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
* as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a member is supposed
* to be autowired.
*/
// 下面两个方法可以自定义支持的依赖注入注解类型
public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
this.autowiredAnnotationTypes.clear();
this.autowiredAnnotationTypes.add(autowiredAnnotationType);
}
/**
* Set the 'autowired' annotation types, to be used on constructors, fields,
* setter methods, and arbitrary config methods.
* <p>The default autowired annotation types are the Spring-provided
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
* as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation types to indicate that a member is supposed
* to be autowired.
*/
public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
this.autowiredAnnotationTypes.clear();
this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
}
/**
* Set the name of an attribute of the annotation that specifies whether it is required.
* @see #setRequiredParameterValue(boolean)
*/
public void setRequiredParameterName(String requiredParameterName) {
this.requiredParameterName = requiredParameterName;
}
/**
* Set the boolean value that marks a dependency as required.
* <p>For example if using 'required=true' (the default), this value should be
* {@code true}; but if using 'optional=false', this value should be {@code false}.
* @see #setRequiredParameterName(String)
*/
public void setRequiredParameterValue(boolean requiredParameterValue) {
this.requiredParameterValue = requiredParameterValue;
}
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
// bean工厂必须是ConfigurableListableBeanFactory的(此处放心使用,唯独只有SimpleJndiBeanFactory不是它的子类而已~)
@Override
public void setBeanFactory(BeanFactory beanFactory) {
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
}
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
// 第一个非常重要的核心方法~~~
//它负责1、解析@Autowired等注解然后转换
// 2、把注解信息转换为InjectionMetadata然后缓存到上面的injectionMetadataCache里面
// postProcessMergedBeanDefinition的执行时机非常早,在doCreateBean()前部分完成bean定义信息的合并
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// findAutowiringMetadata方法重要,完成了解析注解、缓存下来的操作
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
@Override
public void resetBeanDefinition(String beanName) {
this.lookupMethodsChecked.remove(beanName);
this.injectionMetadataCache.remove(beanName);
}
@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
throws BeanCreationException {
// Let's check for lookup methods here...
if (!this.lookupMethodsChecked.contains(beanName)) {
if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
try {
Class<?> targetClass = beanClass;
do {
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Lookup lookup = method.getAnnotation(Lookup.class);
if (lookup != null) {
Assert.state(this.beanFactory != null, "No BeanFactory available");
LookupOverride override = new LookupOverride(method, lookup.value());
try {
RootBeanDefinition mbd = (RootBeanDefinition)
this.beanFactory.getMergedBeanDefinition(beanName);
mbd.getMethodOverrides().addOverride(override);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(beanName,
"Cannot apply @Lookup to beans without corresponding bean definition");
}
}
});
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
}
}
this.lookupMethodsChecked.add(beanName);
}
// Quick check on the concurrent map first, with minimal locking.
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
// Fully synchronized resolution now...
synchronized (this.candidateConstructorsCache) {
candidateConstructors = this.candidateConstructorsCache.get(beanClass);
if (candidateConstructors == null) {
Constructor<?>[] rawCandidates;
try {
rawCandidates = beanClass.getDeclaredConstructors();
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
Constructor<?> requiredConstructor = null;
Constructor<?> defaultConstructor = null;
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
int nonSyntheticConstructors = 0;
for (Constructor<?> candidate : rawCandidates) {
if (!candidate.isSynthetic()) {
nonSyntheticConstructors++;
}
else if (primaryConstructor != null) {
continue;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
if (ann == null) {
Class<?> userClass = ClassUtils.getUserClass(beanClass);
if (userClass != beanClass) {
try {
Constructor<?> superCtor =
userClass.getDeclaredConstructor(candidate.getParameterTypes());
ann = findAutowiredAnnotation(superCtor);
}
catch (NoSuchMethodException ex) {
// Simply proceed, no equivalent superclass constructor found...
}
}
}
if (ann != null) {
if (requiredConstructor != null) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructor: " + candidate +
". Found constructor with 'required' Autowired annotation already: " +
requiredConstructor);
}
boolean required = determineRequiredStatus(ann);
if (required) {
if (!candidates.isEmpty()) {
throw new BeanCreationException(beanName,
"Invalid autowire-marked constructors: " + candidates +
". Found constructor with 'required' Autowired annotation: " +
candidate);
}
requiredConstructor = candidate;
}
candidates.add(candidate);
}
else if (candidate.getParameterCount() == 0) {
defaultConstructor = candidate;
}
}
if (!candidates.isEmpty()) {
// Add default constructor to list of optional constructors, as fallback.
if (requiredConstructor == null) {
if (defaultConstructor != null) {
candidates.add(defaultConstructor);
}
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
"': single autowire-marked constructor flagged as optional - " +
"this constructor is effectively required since there is no " +
"default constructor to fall back to: " + candidates.get(0));
}
}
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
candidateConstructors = new Constructor<?>[0];
}
this.candidateConstructorsCache.put(beanClass, candidateConstructors);
}
}
}
return (candidateConstructors.length > 0 ? candidateConstructors : null);
}
@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;
}
@Deprecated
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
return postProcessProperties(pvs, bean, beanName);
}
/**
* 'Native' processing method for direct calls with an arbitrary target instance,
* resolving all of its fields and methods which are annotated with one of the
* configured 'autowired' annotation types.
* @param bean the target instance to process
* @throws BeanCreationException if autowiring failed
* @see #setAutowiredAnnotationTypes(Set)
*/
public void processInjection(Object bean) throws BeanCreationException {
Class<?> clazz = bean.getClass();
InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
try {
metadata.inject(bean, null, null);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
"Injection of autowired dependencies failed for class [" + clazz + "]", ex);
}
}
// 方法名为查找到该bean的依赖注入元信息,内部只要查找到了就会加入到缓存内,下次没必要再重复查找了~
// 它是一个模版方法,真正做事的方法是:buildAutowiringMetadata 它复杂把标注有@Autowired注解的属性转换为Metadata元数据信息 从而消除注解的定义
// 此处查找包括了字段依赖注入和方法依赖注入~~~
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;
}
// 这里我认为是整个依赖注入前期工作的精髓所在,简单粗暴的可以理解为:它把以依赖注入都转换为InjectionMetadata元信息,待后续使用
// 这里会处理字段注入、方法注入~~~
// 注意:Autowired使用在static字段/方法上、0个入参的方法上(不会报错 只是无效)
// 显然方法的访问级别、是否final都是可以正常被注入进来的~~~
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
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 -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
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))) {
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);
}
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
/**
* Determine if the annotated field or method requires its dependency.
* <p>A 'required' dependency means that autowiring should fail when no beans
* are found. Otherwise, the autowiring process will simply bypass the field
* or method when no beans are found.
* @param ann the Autowired annotation
* @return whether the annotation indicates that a dependency is required
*/
@SuppressWarnings({"deprecation", "cast"})
protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
// The following (AnnotationAttributes) cast is required on JDK 9+.
return determineRequiredStatus((AnnotationAttributes)
ann.asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
}
/**
* Determine if the annotated field or method requires its dependency.
* <p>A 'required' dependency means that autowiring should fail when no beans
* are found. Otherwise, the autowiring process will simply bypass the field
* or method when no beans are found.
* @param ann the Autowired annotation
* @return whether the annotation indicates that a dependency is required
* @deprecated since 5.2, in favor of {@link #determineRequiredStatus(MergedAnnotation)}
*/
@Deprecated
protected boolean determineRequiredStatus(AnnotationAttributes ann) {
return (!ann.containsKey(this.requiredParameterName) ||
this.requiredParameterValue == ann.getBoolean(this.requiredParameterName));
}
/**
* Obtain all beans of the given type as autowire candidates.
* @param type the type of the bean
* @return the target beans, or an empty Collection if no bean of this type is found
* @throws BeansException if bean retrieval failed
*/
protected <T> Map<String, T> findAutowireCandidates(Class<T> type) throws BeansException {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory configured - " +
"override the getBeanOfType method or specify the 'beanFactory' property");
}
return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type);
}
/**
* Register the specified bean as dependent on the autowired beans.
*/
private void registerDependentBeans(@Nullable String beanName, Set<String> autowiredBeanNames) {
if (beanName != null) {
for (String autowiredBeanName : autowiredBeanNames) {
if (this.beanFactory != null && this.beanFactory.containsBean(autowiredBeanName)) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
}
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName +
"' to bean named '" + autowiredBeanName + "'");
}
}
}
}
/**
* Resolve the specified cached method argument or field value.
*/
@Nullable
private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
if (cachedArgument instanceof DependencyDescriptor) {
DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
Assert.state(this.beanFactory != null, "No BeanFactory available");
return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
}
else {
return cachedArgument;
}
}
/**
* Class representing injection information about an annotated field.
*/
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
private final boolean required;
private volatile boolean cached = false;
@Nullable
private volatile Object cachedFieldValue;
public AutowiredFieldElement(Field field, boolean required) {
super(field, null);
this.required = required;
}
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
/**
* Class representing injection information about an annotated method.
*/
private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
private final boolean required;
private volatile boolean cached = false;
@Nullable
private volatile Object[] cachedMethodArguments;
public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {
super(method, pd);
this.required = required;
}
@Override
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) {
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
int argumentCount = method.getParameterCount();
arguments = new Object[argumentCount];
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == argumentCount) {
Iterator<String> it = autowiredBeans.iterator();
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
}
if (arguments != null) {
try {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
@Nullable
private Object[] resolveCachedArguments(@Nullable String beanName) {
Object[] cachedMethodArguments = this.cachedMethodArguments;
if (cachedMethodArguments == null) {
return null;
}
Object[] arguments = new Object[cachedMethodArguments.length];
for (int i = 0; i < arguments.length; i++) {
arguments[i] = resolvedCachedArgument(beanName, cachedMethodArguments[i]);
}
return arguments;
}
}
/**
* DependencyDescriptor variant with a pre-resolved target bean name.
*/
@SuppressWarnings("serial")
private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
private final String shortcut;
private final Class<?> requiredType;
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {
super(original);
this.shortcut = shortcut;
this.requiredType = requiredType;
}
@Override
public Object resolveShortcut(BeanFactory beanFactory) {
return beanFactory.getBean(this.shortcut, this.requiredType);
}
}
}
为什么@Autowired没有生效?
这个问题是有一次小伙伴私聊问我的,我把它放在此处,希望能帮助到遇到类似情况的小伙伴们。
我们知道我们使用@Autowired注入Bean,要么就报错,要么就正常work,那么何来不生效的情况呢(不生效指的是值没注入进入,仍为null)?(注意:不考虑requied=false的情况)
我个人总结如下两点,若遇到同样问题,可从下面着手去定位:
你@Autowired依赖的Bean以及@Autowired所在Bean是否交给Spring容器管理了?
- Tips:虽然依赖注入中@Autowired所在的Bean并不必须得交给Spring容器管理,但此处不考虑这种case(因为我预估很少人知道这个知识点并且还能会用这个知识点,对于此知识点有兴趣的参考博文:【小家Spring】为脱离Spring IOC容器管理的Bean赋能【依赖注入】的能力,并分析原理(借助AutowireCapableBeanFactory赋能)) 你@Autowired所在的Bean的初始化时机是否比AutowiredAnnotationBeanPostProcessor还早?
- @Autowired注解必须靠AutowiredAnnotationBeanPostProcessor才能解析。而它虽然实现了PriorityOrdered接口,但是它毕竟还是个BeanPostProcessor,所以生效时机还是会晚于BeanFactoryPostProcessor的,所以若你在BeanFactoryPostProcessor里getBean(),那依赖注入铁定不生效呀~