spring中自動注入注解的實現(xiàn)方式
在前面的文章中,我們介紹過,基于注解的包掃描模式下,會默認(rèn)注冊一系列的后置處理器,其中,就包含一個 AutowiredAnnotationBeanPostProcessor,這個處理器默認(rèn)就會處理 @Autowired 和 @Value 注解。
類結(jié)構(gòu)
從圖中可知,這是一個 MergedBeanDefinitionPostProcessor 實現(xiàn)類,所以會在每一個實例對象創(chuàng)建時,當(dāng)實例化結(jié)束,還未提前暴露時,對實例對象進(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 上定義的注解,此時封裝為 TypeMappedAnnotations,接著獲取指定注入注解類型對應(yīng)的 TypeMappedAnnotation,存在,返回 TypeMappedAnnotation,從中獲取注解屬性 "required" 對應(yīng)的值,默認(rèn) true,之后將 Field 或 Method 封裝成 InjectionMetadata.InjectedElement,加入 elements 集合,最后包裝成 InjectionMetadata,放入 AutowiredAnnotationBeanPostProcessor 中 injectionMetadataCache 緩存。
有一點(diǎn)要注意,就是 Method 注入時,雖然獲取了 pd,但測試中 pd 為 null,也不影響注入,由此也說明注入的方法不一定必須是 setter 或 getter 方法。
注入
實例化完 bean 之后,進(jìn)行屬性填充,執(zhí)行 AbstractAutowireCapableBeanFactory#populateBean,此時會調(diào)用 InstantiationAwareBeanPostProcessor#postProcessProperties,AutowiredAnnotationBeanPostProcessor 實現(xiàn)了這個方法。
@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)介紹過了,此時會直接從緩存獲取到 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); } } }
遍歷,對每個 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)建了一個 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(); // 解析每一個參數(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 注入,都是先封裝出一個 DependencyDescriptor,接著執(zhí)行 beanFactory.resolveDependency 進(jìn)行依賴的解析,不同點(diǎn)在于 Field 解析完就返回了,而 Method 解析完是為了構(gòu)造出參數(shù)數(shù)組。
之后,不管是 Field 注入,還是 Method 注入,都是利用反射完成注入。這也說明,Method 注入時,只要能正常的封裝出參數(shù)數(shù)組,就能完成屬性或字段注入。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
IDEA 2020.3 更新了機(jī)器學(xué)習(xí)都整上了
IDEA 歡迎窗口全新升級,首頁增加三個選項卡,一個用于設(shè)置 IDE 界面的 Customize,一個用于插件安裝的 Plugins,一個于訪問幫助和學(xué)習(xí)資源的 Learn IntelliJ IDEA,另外包括之前用于管理項目的 Projects,需要的朋友可以參考下2020-12-12Spring?AOP操作的相關(guān)術(shù)語及環(huán)境準(zhǔn)備
這篇文章主要為大家介紹了Spring?AOP操作的相關(guān)術(shù)語及環(huán)境準(zhǔn)備學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05