• 【Spring-5.2】AbstractAutowireCapableBeanFactory#populateBean实现Bean的属性赋值


    本章是属性注入的详细分析

    默认情况下,spring不会主动给bean注入是属性的,开发者需要自己配置,首先明确的是对象有哪些属性需要注入,注入的类型是按照类型还是按照名称。之前这些可以在xml文件中配置,但是在开发中最好是通过注解的方式实现,所以用到了@autowired,@resource注解,需要注入的属性,使用注解标注即可。spring是怎么知道对象中哪些属性用注解标注了呢?

    进入方法AbstractAutowireCapableBeanFactory#doCreateBean,在创建完实例之后,有一步调用处理器的postProcessMergedBeanDefinition方法,属性注入之前对bd的最后操作。

    		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;
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    bean处理器中有两个是用来处理@autowired,@resource注解的
    AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
    两个处理器的逻辑大致相似,本文以AutowiredAnnotationBeanPostProcessor处理器为例进行分析,下面进入到AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition方法

    	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    		// InjectionMetadata 保存了这个bean的需要注入的属性
    		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    		metadata.checkConfigMembers(beanDefinition);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    构建保存实例属性的对象InjectionMetadata。

    	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    		// 
    		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    		// 从缓存中取数据
    		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    		// 如果数据是null 或者数据中保存的对象和clazz对不上了,就需要刷新,进入方法
    		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;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    从缓存中取数据,如果没有就直接构建对象。

    	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    		// 是否这个类的属性有用注解标注的属性(@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<>();
    			// 利用反射得到这个类的属性,根据属性得到属性上的注解
    			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);
    		// 创建InjectionMetadata对象
    		return InjectionMetadata.forElements(elements, clazz);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    根据反射得到类的属性,如果属性有@autowired注解,就先将该属性信息创建AutowiredFieldElement对象,得到所有的属性集合,创建InjectionMetadata信息。可以看到InjectionMetadata保存了目标bean的class信息和需要注入的属性集合。注意,关于属性和方法,静态的都不能注入。

    下面开始进入属性注入AbstractAutowireCapableBeanFactory#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;
    			}
    		}
    
    		// 实例化之后的操作,如果返回的是false,就不在注入了。
    		// 实例化处理器的实例化之后的处理器方法
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    					return;
    				}
    			}
    		}
    		
    		//先看bd中是否已经设置了需要注入的属性。通常有值的都是xml配置的,或者是自定义的bd.
    		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    		
    		// 默认是不注入的AUTOWIRE_NO
    		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    			// 通过名称找到 key: propertyName, value:bean
    			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
    				autowireByName(beanName, mbd, bw, newPvs);
    			}
    			// 通过类型找
    			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    				autowireByType(beanName, mbd, bw, newPvs);
    			}
    			// 无论是按照名称注入还是按照类型注入,会把实例和属性名称保存在newPvs中,现在还没有注入属性呢
    			pvs = newPvs;
    		}
    		// 上面的逻辑过后,newPvs中的集合中对象类似一个k-v对,key是属性,value是注入的对象。
    
    		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) {
    				// 这里的是处理属性的处理器,其实就是保存@autowired和@resource注解的处理器。这里有注入逻辑,通过field,得到相应的bean,最后通过反射给属性赋值。
    				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;
    			}
    		}
    		if (needsDepCheck) {
    			if (filteredPds == null) {
    				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    			}
    			checkDependencies(beanName, mbd, filteredPds, pvs);
    		}
    		// 通过名称或类型的在这步赋值。
    		if (pvs != null) {
    			applyPropertyValues(beanName, mbd, bw, pvs);
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    先梳理下流程,从bd中找到注入的属性,根据注入的类型,从beanFactory中取出对应的对象。放入到MutablePropertyValues 中,最后通过applyPropertyValues方法,反射给属性赋值。如果是通过注解的方式处理注入的,是通过处理器,即上面已经提到的处理器。进行处理。

    由于支持注解开发模式和xml文件配置的开发模式。所以这块代码看起来混乱。可以这么理解,注解的处理是在处理器中,xml中的已经保存在了bd中,从bd中取出PropertyValues,最后用beanWrapper进行属性注入,本质是反射调用set方法。而注解的本质是属性的反射赋值


    下面看下注解方式是如何注入的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;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    	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);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    		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);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    是核心方法。

    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    
    • 1
    	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
    			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
    		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    		if (Optional.class == descriptor.getDependencyType()) {
    			return createOptionalDependency(descriptor, requestingBeanName);
    		}
    		else if (ObjectFactory.class == descriptor.getDependencyType() ||
    				ObjectProvider.class == descriptor.getDependencyType()) {
    			return new DependencyObjectProvider(descriptor, requestingBeanName);
    		}
    		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
    			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
    		}
    		else {
    			// 不同类型走不同的逻辑
    			// 一般情况下,走这块:
    			// 从属性找是否有@lazy注解,有的话,就创建一个代理对象懒注册。
    			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
    					descriptor, requestingBeanName);
    			if (result == null) {
    				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
    			}
    			return result;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);放用来找Lazy注解,实现懒加载。用到的时候在取找对象。

    	protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
    		Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,
    				"BeanFactory needs to be a DefaultListableBeanFactory");
    		final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();
    		TargetSource ts = new TargetSource() {
    			@Override
    			public Class<?> getTargetClass() {
    				return descriptor.getDependencyType();
    			}
    			@Override
    			public boolean isStatic() {
    				return false;
    			}
    			@Override
    			public Object getTarget() {
    				Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);
    				if (target == null) {
    					Class<?> type = getTargetClass();
    					if (Map.class == type) {
    						return Collections.emptyMap();
    					}
    					else if (List.class == type) {
    						return Collections.emptyList();
    					}
    					else if (Set.class == type || Collection.class == type) {
    						return Collections.emptySet();
    					}
    					throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
    							"Optional dependency not present for lazy injection point");
    				}
    				return target;
    			}
    			@Override
    			public void releaseTarget(Object target) {
    			}
    		};
    		ProxyFactory pf = new ProxyFactory();
    		pf.setTargetSource(ts);
    		Class<?> dependencyType = descriptor.getDependencyType();
    		if (dependencyType.isInterface()) {
    			pf.addInterface(dependencyType);
    		}
    		return pf.getProxy(beanFactory.getBeanClassLoader());
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    如果不用懒加载,就直接总bean工厂中找对象。doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

    	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
    		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    		try {
    			Object shortcut = descriptor.resolveShortcut(this);
    			if (shortcut != null) {
    				return shortcut;
    			}
    
    			Class<?> type = descriptor.getDependencyType();
    
    
    
    			// 是否有Value注解。
    			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
    			// 处理value注解
    			if (value != null) {
    				if (value instanceof String) {
    					String strVal = resolveEmbeddedValue((String) value);
    					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
    							getMergedBeanDefinition(beanName) : null);
    					value = evaluateBeanDefinitionString(strVal, bd);
    				}
    				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
    				try {
    					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
    				}
    				catch (UnsupportedOperationException ex) {
    					// A custom TypeConverter which does not support TypeDescriptor resolution...
    					return (descriptor.getField() != null ?
    							converter.convertIfNecessary(value, type, descriptor.getField()) :
    							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
    				}
    			}
    
    
    
    			// 是否是复杂类型的,比如数组,集合,map等
    			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
    			if (multipleBeans != null) {
    				return multipleBeans;
    			}
    
    
    			// 普通的类型的
    			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    			if (matchingBeans.isEmpty()) {
    				if (isRequired(descriptor)) {
    					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    				}
    				return null;
    			}
    
    			String autowiredBeanName;
    			Object instanceCandidate;
    			// 如果能选出多个候选的bean
    			if (matchingBeans.size() > 1) {
    				// 过滤出一个合适的bean
    				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    				// 如果没选出来,这个bean优势必须的,直接抛异常
    				if (autowiredBeanName == null) {
    					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
    						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
    					}
    					else {
    						// In case of an optional Collection/Map, silently ignore a non-unique case:
    						// possibly it was meant to be an empty collection of multiple regular beans
    						// (before 4.3 in particular when we didn't even look for collection beans).
    						return null;
    					}
    				}
    				instanceCandidate = matchingBeans.get(autowiredBeanName);
    			}
    			else {
    				// We have exactly one match.
    				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
    				autowiredBeanName = entry.getKey();
    				instanceCandidate = entry.getValue();
    			}
    
    			if (autowiredBeanNames != null) {
    				autowiredBeanNames.add(autowiredBeanName);
    			}
    			// 实例化bean
    			if (instanceCandidate instanceof Class) {
    				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    			}
    			Object result = instanceCandidate;
    			if (result instanceof NullBean) {
    				if (isRequired(descriptor)) {
    					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    				}
    				result = null;
    			}
    			if (!ClassUtils.isAssignableValue(type, result)) {
    				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
    			}
    			return result;
    		}
    		finally {
    			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104

    解析@Value注解的。
    如果类型是复杂的如,数组,集合,map,处理。
    普通类型的。通过findAutowireCandidates找出所有合适的。在通过determineAutowireCandidate找出用哪个。


    findAutowireCandidates:

    	protected Map<String, Object> findAutowireCandidates(
    			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    		// 找出所有类型符合的
    		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    				this, requiredType, true, descriptor.isEager());
    
    
    		Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
    		for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
    			Class<?> autowiringType = classObjectEntry.getKey();
    			if (autowiringType.isAssignableFrom(requiredType)) {
    				Object autowiringValue = classObjectEntry.getValue();
    				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
    				if (requiredType.isInstance(autowiringValue)) {
    					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
    					break;
    				}
    			}
    		}
    
    		// 这里进行了筛选,
    		// isAutowireCandidate是筛选逻辑;
    		// 里面有反射的条件筛选,同时如果有@Qualifiers注解,检查是否符合要求
    		
    		for (String candidate : candidateNames) {
    			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
    				addCandidateEntry(result, candidate, descriptor, requiredType);
    			}
    		}
    		
    		// 如果没有合适的,那么就放宽要求。
    		if (result.isEmpty()) {
    			boolean multiple = indicatesMultipleBeans(requiredType);
    			// 考虑泛型不用精确匹配。
    			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
    			for (String candidate : candidateNames) {
    				if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
    						(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
    					addCandidateEntry(result, candidate, descriptor, requiredType);
    				}
    			}
    			// 如果还是没有,再次放宽要求,可以自已引用自己
    			if (result.isEmpty() && !multiple) {
    				// Consider self references as a final pass...
    				// but in the case of a dependency collection, not the very same bean itself.
    				for (String candidate : candidateNames) {
    					if (isSelfReference(beanName, candidate) &&
    							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
    							isAutowireCandidate(candidate, fallbackDescriptor)) {
    						addCandidateEntry(result, candidate, descriptor, requiredType);
    					}
    				}
    			}
    		}
    		return result;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    这块有泛型的匹配。如果要注入的类型没有泛型例如private HelloService helloService ,那么匹配的时候会加上泛型适配符HelloService,这样所有同类型的泛型都符合要求。但是如果注入的是有明确泛型的比如:HelloService那么泛型匹配就严格匹配。需要一模一样。 ,是不同的,不会认为String继承自Object,就可以注入。泛型的匹配没有关系,就是严格一样。

    具体还是看这篇文章。【小家Spring】细说Spring IOC容器的自动装配(@Autowired),以及Spring4.0新特性之【泛型依赖注入】的源码级解析


    如果有多个符合怎么办呢?
    通过方法determineAutowireCandidate筛选。

    	protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
    		Class<?> requiredType = descriptor.getDependencyType();
    		String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
    		if (primaryCandidate != null) {
    			return primaryCandidate;
    		}
    		String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
    		if (priorityCandidate != null) {
    			return priorityCandidate;
    		}
    		// Fallback
    		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
    			String candidateName = entry.getKey();
    			Object beanInstance = entry.getValue();
    			if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
    					matchesBeanName(candidateName, descriptor.getDependencyName())) {
    				return candidateName;
    			}
    		}
    		return null;
    	}
    	
    	// 找Primary的,但让设置了过个肯定是报错的。如果没有设置,返回null
    	protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    		String primaryBeanName = null;
    		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
    			String candidateBeanName = entry.getKey();
    			Object beanInstance = entry.getValue();
    			// 如果标注了@Primary
    			if (isPrimary(candidateBeanName, beanInstance)) {	
    				
    				// 如果都标注了,就保存了
    				if (primaryBeanName != null) {
    					boolean candidateLocal = containsBeanDefinition(candidateBeanName);
    					boolean primaryLocal = containsBeanDefinition(primaryBeanName);
    					if (candidateLocal && primaryLocal) {
    						throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
    								"more than one 'primary' bean found among candidates: " + candidates.keySet());
    					}
    					else if (candidateLocal) {
    						primaryBeanName = candidateBeanName;
    					}
    				}
    				else {
    					primaryBeanName = candidateBeanName;
    				}
    			}
    		}
    		return primaryBeanName;
    	}
    
    	
    	// 标注了Priority,有了优先级,数值越低,优先级越高。当然了,如果没有标注,返回null,标记值一样报错。
    	protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    		String highestPriorityBeanName = null;
    		Integer highestPriority = null;
    		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
    			String candidateBeanName = entry.getKey();
    			Object beanInstance = entry.getValue();
    			if (beanInstance != null) {
    				Integer candidatePriority = getPriority(beanInstance);
    				if (candidatePriority != null) {
    					if (highestPriorityBeanName != null) {
    						if (candidatePriority.equals(highestPriority)) {
    							throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
    									"Multiple beans found with the same priority ('" + highestPriority +
    									"') among candidates: " + candidates.keySet());
    						}
    						else if (candidatePriority < highestPriority) {
    							highestPriorityBeanName = candidateBeanName;
    							highestPriority = candidatePriority;
    						}
    					}
    					else {
    						highestPriorityBeanName = candidateBeanName;
    						highestPriority = candidatePriority;
    					}
    				}
    			}
    		}
    		return highestPriorityBeanName;
    	}
    
    	// 如果还不能区分,就按照属性的名称和bean的名称比较,相等的为符合的。
    	protected boolean matchesBeanName(String beanName, @Nullable String candidateName) {
    		return (candidateName != null &&
    				(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    在都符合的时候,通过人为干预,选取合适的。
    先进行@primary的筛选,指定了,有指定的,指定多了就报错;没有指定,继续下面的。
    通过优先级,数值低,优先级高,没有指定,还是无法筛选,返回null,优先级一样,报错。
    还不行,按照属性的名称匹配。,还不行,spring也不知道用哪个了,返回null.
    如果是必须的,抛异常throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());

    所以按照类型注入什么时候会报错呢?就是找到了多个,没有找到就返回null了。


    CommonAnnotationBeanPostProcessor

    使用@Resource注入,需要明确是@Resource不是Spring的注解,是JSR标准

    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties直接看这个注入的方法了,其实在依赖输入之前,postProcessMergedBeanDefinition这个方法会进行依赖注入的解析,保存缓存中,在postProcessProperties是从缓存找取,执行注入逻辑。所以直接看postProcessProperties方法也无妨。

    	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    		// 缓存了需要输入数据的信息
    		InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    		try {
    			// 注入逻辑。
    			metadata.inject(bean, beanName, pvs);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    		}
    		return pvs;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata
    解析需要注入的信息

    	private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
    		if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
    			return InjectionMetadata.EMPTY;
    		}
    
    		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    		Class<?> targetClass = clazz;
    
    		do {
    			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    			// 得到所有的属性信息
    			ReflectionUtils.doWithLocalFields(targetClass, field -> {
    				// 兼容其他注解
    				。。。。。。
    				// 我们只关注Resource注解的。
    				else if (field.isAnnotationPresent(Resource.class)) {
    					// 静态的属性不能注入
    					if (Modifier.isStatic(field.getModifiers())) {
    						throw new IllegalStateException("@Resource annotation is not supported on static fields");
    					}
    					// 将属性封装为ResourceElement
    					if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
    						currElements.add(new ResourceElement(field, field, null));
    					}
    				}
    			});
    
    			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    					return;
    				}
    				if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {				
    					// 兼容其他注解
    					。。。。。
    
    					// 只看Resource注解
    					else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
    						// 静态的方法不能注入
    						if (Modifier.isStatic(method.getModifiers())) {
    							throw new IllegalStateException("@Resource annotation is not supported on static methods");
    						}
    						// 方法参数个数不是1的会抛异常。
    						Class<?>[] paramTypes = method.getParameterTypes();
    						if (paramTypes.length != 1) {
    							throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
    						}
    						// 封装为ResourceElement
    						if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
    							PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    							currElements.add(new ResourceElement(method, bridgedMethod, pd));
    						}
    					}
    				}
    			});
    
    			elements.addAll(0, currElements);
    			targetClass = targetClass.getSuperclass();
    		}
    		// 循环,从父类中是否有标注注解的。
    		while (targetClass != null && targetClass != Object.class);
    
    		return InjectionMetadata.forElements(elements, clazz);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    解析注解:

    1. 静态属性和静态方法不能出入;
    2. 方法的参数个数必须是1个,否则会跑异常。
    3. 将数据给封装在ResourceElement再添加到集合中。

    注入逻辑:

    	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()) {
    			// 遍历InjectedElement集合,调用InjectedElement 的注入方法。
    			for (InjectedElement element : elementsToIterate) {
    				if (logger.isTraceEnabled()) {
    					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
    				}
    				element.inject(target, beanName, pvs);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    		protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
    				throws Throwable {
    			// 属性,通过反射
    			if (this.isField) {
    				Field field = (Field) this.member;
    				ReflectionUtils.makeAccessible(field);
    				field.set(target, getResourceToInject(target, requestingBeanName));
    			}
    			else {
    				if (checkPropertySkipping(pvs)) {
    					return;
    				}
    				try {
    					// 方法,方法的反射。
    					Method method = (Method) this.member;
    					ReflectionUtils.makeAccessible(method);
    					method.invoke(target, getResourceToInject(target, requestingBeanName));
    				}
    				catch (InvocationTargetException ex) {
    					throw ex.getTargetException();
    				}
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    getResourceToInject通过该方法得到值;
    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject

    		protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
    			//这里有一个懒加载的操作。
    			// 如果使用@lazy注解标注了,会给创建一个代理,只有再使用的时候才会取bean工厂中找bean
    			//非懒加载的会立刻执行找bean的逻辑,返回结果。懒加载是先返回要给代理,等调用放的时候再去执行找bean的过程。
    			return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
    					getResource(this, requestingBeanName));
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    	protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
    			throws NoSuchBeanDefinitionException {
    
    		Object resource;
    		Set<String> autowiredBeanNames;
    		// 如果是属性,这里是注解value的值,没有指定,就是属性的名称
    		// 如果是方法,javabean标准,是属性名称;不是javaBean标准,则是方法名称。
    		String name = element.name;
    
    		if (factory instanceof AutowireCapableBeanFactory) {
    			AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
    			DependencyDescriptor descriptor = element.getDependencyDescriptor();
    			// 如果按照名称找,但是名称没有,就按类型找。
    			if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
    				autowiredBeanNames = new LinkedHashSet<>();
    				resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
    				if (resource == null) {
    					throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
    				}
    			}
    			// 按照名称找。
    			else {
    				resource = beanFactory.resolveBeanByName(name, descriptor);
    				autowiredBeanNames = Collections.singleton(name);
    			}
    		}
    		else {
    			resource = factory.getBean(name, element.lookupType);
    			autowiredBeanNames = Collections.singleton(name);
    		}
    
    		if (factory instanceof ConfigurableBeanFactory) {
    			ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
    			for (String autowiredBeanName : autowiredBeanNames) {
    				if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
    					beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
    				}
    			}
    		}
    
    		return resource;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    按照名称找不到,就会按照类型找。

    		public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
    			super(member, pd);
    			Resource resource = ae.getAnnotation(Resource.class);
    			// Resource 指定的bean名称
    			String resourceName = resource.name();
    			Class<?> resourceType = resource.type();
    			this.isDefaultName = !StringUtils.hasLength(resourceName);
    			// 如果使用默认的名称
    			if (this.isDefaultName) {
    				// 属性名称或者方法名称
    				resourceName = this.member.getName();
    				// 如果是方法,兵器是set开头,长度>3,是javaBean规范
    				// 内省机制找到属性名。否则还是方法名称。
    				if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
    					resourceName = Introspector.decapitalize(resourceName.substring(3));
    				}
    			}
    			else if (embeddedValueResolver != null) {
    				resourceName = embeddedValueResolver.resolveStringValue(resourceName);
    			}
    			if (Object.class != resourceType) {
    				checkResourceType(resourceType);
    			}
    			else {
    				// No resource type specified... check field/method.
    				resourceType = getResourceType();
    			}
    			this.name = (resourceName != null ? resourceName : "");
    			this.lookupType = resourceType;
    			String lookupValue = resource.lookup();
    			this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
    			Lazy lazy = ae.getAnnotation(Lazy.class);
    			this.lazyLookup = (lazy != null && lazy.value());
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    关于根据名称找的问题;如果注解给了名称,使用该名称,没有给,就用属性自己的。如果是注释在方法上,如果是符合JavaBean规范,那么用的将是属性名称,否则用的是方法名称。


    有个问题;静态的属性和方法都还不能用注解,那如果就是想用静态的怎么版呢?

    解决静态属性,静态方法注入的问题

    就是通过普通方法给静态属性赋值

    @Component
    public class UserHelper {
    
        static UCClient ucClient;
    
        @Autowired
        public void setUcClient(UCClient ucClient) {
            UserHelper.ucClient = ucClient;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    但是想想工具类都是静态的,不用交给spring管理。
    SmartInitializingSingleton该接口会在所有的bean都实例化之后调用

    @Component
    public class AutowireStaticSmartInitializingSingleton implements SmartInitializingSingleton {
    
        @Autowired
        private AutowireCapableBeanFactory beanFactory;
    
        /**
         * 当所有的单例Bena初始化完成后,对static静态成员进行赋值
         */
        @Override
        public void afterSingletonsInstantiated() {
            // 交给工厂,给我注如,
            beanFactory.autowireBean(new UserHelper());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这样该类就不用加@Component注解。工具类交给beanFactory,让工厂注入。

    public class UserHelper {
    
        static UCClient ucClient;
        @Autowired
        public void setUcClient(UCClient ucClient) {
            UserHelper.ucClient = ucClient;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    或者这样:

    @Component
    public class AutowireStaticSmartInitializingSingleton implements SmartInitializingSingleton {
    
        @Autowired
        private AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor;
        // 就是让处理器给注入
        @Override
        public void afterSingletonsInstantiated() {
            autowiredAnnotationBeanPostProcessor.processInjection(new UserHelper());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    【OpenVINO™】YOLOv10在CPU上也能实现50+FPS推理—使用OpenVINO C++部署YOLOv10
    LINUX中的vi/vim命令
    智能网联驾驶测试与评价工业和信息化部重点实验室“车载智能计算基础平台参考架构2.0专家研讨会”圆满结束
    近期的ABAP FI开发总结
    Mybatis Plus 框架项目落地实践总结
    dolphinscheduler 2.0.6 任务之间的参数传递及Java脚本引擎
    实在智能携手中国电信翼支付,全球首款Agent智能体亮相2023数字科技生态大会
    昆仑万维旗下StarMaker VR成功加入Oculus开发者计划 获Oculus资金支持
    LLVM系列第二十八章:写一个JIT Hello World
    【数据结构】时间复杂度_空间复杂度
  • 原文地址:https://blog.csdn.net/qq_34501351/article/details/114292009