spring中自動注入注解的實(shí)現(xiàn)方式
在前面的文章中,我們介紹過,基于注解的包掃描模式下,會默認(rèn)注冊一系列的后置處理器,其中,就包含一個(gè) AutowiredAnnotationBeanPostProcessor,這個(gè)處理器默認(rèn)就會處理 @Autowired 和 @Value 注解。
類結(jié)構(gòu)

從圖中可知,這是一個(gè) MergedBeanDefinitionPostProcessor 實(shí)現(xiàn)類,所以會在每一個(gè)實(shí)例對象創(chuàng)建時(shí),當(dāng)實(shí)例化結(jié)束,還未提前暴露時(shí),對實(shí)例對象進(jìn)行處理。
// AutowiredAnnotationBeanPostProcessor
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}獲取注解
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// 確定緩存 key
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 從緩存獲取 InjectionMetadata
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
// metadata 為 null,表示需要刷新
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 創(chuàng)建 metadata
metadata = buildAutowiringMetadata(clazz);
// 放入緩存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
// autowiredAnnotationTypes 兩種類型 @Autowired/@Value
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<>();
// 處理 Field 上注解
ReflectionUtils.doWithLocalFields(targetClass, field -> {
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// static 不支持注入
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 默認(rèn) true
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
// 處理 Method 上注解
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);
// Method 比 Field 多了 PropertyDescriptor
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) {
// TypeMappedAnnotations
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
// 獲取指定 type 對應(yīng)的 TypeMappedAnnotation,存在,將對應(yīng)的 TypeMappedAnnotation 返回
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}可以看到,獲取當(dāng)前類及其父類中 Field 或 Method 上定義的注解,此時(shí)封裝為 TypeMappedAnnotations,接著獲取指定注入注解類型對應(yīng)的 TypeMappedAnnotation,存在,返回 TypeMappedAnnotation,從中獲取注解屬性 "required" 對應(yīng)的值,默認(rèn) true,之后將 Field 或 Method 封裝成 InjectionMetadata.InjectedElement,加入 elements 集合,最后包裝成 InjectionMetadata,放入 AutowiredAnnotationBeanPostProcessor 中 injectionMetadataCache 緩存。
有一點(diǎn)要注意,就是 Method 注入時(shí),雖然獲取了 pd,但測試中 pd 為 null,也不影響注入,由此也說明注入的方法不一定必須是 setter 或 getter 方法。
注入
實(shí)例化完 bean 之后,進(jìn)行屬性填充,執(zhí)行 AbstractAutowireCapableBeanFactory#populateBean,此時(shí)會調(diào)用 InstantiationAwareBeanPostProcessor#postProcessProperties,AutowiredAnnotationBeanPostProcessor 實(shí)現(xiàn)了這個(gè)方法。
@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 前面已經(jīng)介紹過了,此時(shí)會直接從緩存獲取到 InjectionMetadata。
// InjectionMetadata
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);
}
}
}遍歷,對每個(gè) InjectedElement,調(diào)用 inject 方法。從上面介紹可知,InjectedElement 共兩種,分別是針對 Field 的 AutowiredFieldElement,以及針對 Method 的 AutowiredMethodElement。下面分別介紹。
Field 注入
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
// false
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);
}
}
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
// 創(chuàng)建了一個(gè) SimpleTypeConverter 作為 typeConverter
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
// 解析依賴,對于基本類型,解析后經(jīng)過轉(zhuǎn)換返回包裝類型
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}邏輯比較簡單,解析出注入的值,接著反射注入值。
Method 注入
@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) {
try {
arguments = resolveCachedArguments(beanName);
}
catch (NoSuchBeanDefinitionException ex) {
// Unexpected removal of target bean for cached argument -> re-resolve
arguments = resolveMethodArguments(method, bean, beanName);
}
}
else {
// 解析參數(shù)
arguments = resolveMethodArguments(method, bean, beanName);
}
if (arguments != null) {
try {
// 反射調(diào)用方法,注入屬性
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
@Nullable
private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {
int argumentCount = method.getParameterCount();
Object[] 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();
// 解析每一個(gè)參數(shù)
for (int i = 0; i < arguments.length; i++) {
// 封裝 MethodParameter
MethodParameter methodParam = new MethodParameter(method, i);
// 封裝 DependencyDescriptor
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
// 解析依賴,required 默認(rèn) true,遇見無法解析的直接拋出異常
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
// 構(gòu)造參數(shù)
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;
}
}
return arguments;
}可以看到,不管是 Field 注入還是 Method 注入,都是先封裝出一個(gè) DependencyDescriptor,接著執(zhí)行 beanFactory.resolveDependency 進(jìn)行依賴的解析,不同點(diǎn)在于 Field 解析完就返回了,而 Method 解析完是為了構(gòu)造出參數(shù)數(shù)組。
之后,不管是 Field 注入,還是 Method 注入,都是利用反射完成注入。這也說明,Method 注入時(shí),只要能正常的封裝出參數(shù)數(shù)組,就能完成屬性或字段注入。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
IDEA 2020.3 更新了機(jī)器學(xué)習(xí)都整上了
IDEA 歡迎窗口全新升級,首頁增加三個(gè)選項(xiàng)卡,一個(gè)用于設(shè)置 IDE 界面的 Customize,一個(gè)用于插件安裝的 Plugins,一個(gè)于訪問幫助和學(xué)習(xí)資源的 Learn IntelliJ IDEA,另外包括之前用于管理項(xiàng)目的 Projects,需要的朋友可以參考下2020-12-12
java微信掃碼支付模式一線下支付功能實(shí)現(xiàn)
本篇文章主要介紹了JAVA微信掃碼支付模式一線下支付功能實(shí)現(xiàn),具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11
SpringBoot文件上傳功能的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot文件上傳功能的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Spring?AOP操作的相關(guān)術(shù)語及環(huán)境準(zhǔn)備
這篇文章主要為大家介紹了Spring?AOP操作的相關(guān)術(shù)語及環(huán)境準(zhǔn)備學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Java編程實(shí)現(xiàn)打印螺旋矩陣實(shí)例代碼
這篇文章主要介紹了Java編程實(shí)現(xiàn)打印螺旋矩陣實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12

