在spring中,我們都用過@Autowire, @Resource, @Inject, @Value這幾個註解,可是我們都知道這些註解標註的屬性值是怎麼裝配到bean中的麼?
問題:首先我們看看這幾個註解的不同?
@Value:將配置文件中,或者環境中的值裝配到bean屬性上
@Autowire與@Inject都是都是由AutowiredAnnotationBeanPostProcessor進行處理的,不同在於@Autowire有required屬性,而@Inject沒有
@Autowire與@Resource由不同的後置處理器進行處理,@Resource由CommonAnnotationBeanPostProcessor進行處理,還有@Autowrie屬於spring註解,而@Resource和@Inject屬於java註解
問題:如何證明@Value, @Inject, @Autowire由AutowiredAnnotationBeanPostProcessor進行處理,而@Resource由CommonAnnotationBeanPostProcessor處理
根據CommonAnnotationBeanPostProcessor類的靜態代碼塊我們可以知道,在類加載的時候就將將Resource.class添加到了resourceAnnotationTypes中了
而在AutowiredAnnotationBeanPostProcessor類的構造方法中,也是將Value, Inject, Autowire添加到了autowiredAnnotationTypes中了
在這兩個類中這兩個屬性在後續屬性裝配是非常重要
//CommonAnnotationBeanPostProcessor 靜態代碼塊
static {
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());
webServiceRefClass = clazz;
}
catch (ClassNotFoundException ex) {
webServiceRefClass = null;
}
try {
@SuppressWarnings("unchecked")
Class<? extends Annotation> clazz = (Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());
ejbRefClass = clazz;
}
catch (ClassNotFoundException ex) {
ejbRefClass = null;
}
//************************************************
//**重點
//默認初始化,添加Resource.class到resourceAnnotationTypes中
resourceAnnotationTypes.add(Resource.class);
if (webServiceRefClass != null) {
resourceAnnotationTypes.add(webServiceRefClass);
}
if (ejbRefClass != null) {
resourceAnnotationTypes.add(ejbRefClass);
}
}
//AutowiredAnnotationBeanPostProcessor構造方法
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.
}
}
問題:屬性裝配發生在什麼時候?
讀取spring bean創建的源碼我們可以找到doCreateBean()這樣一個方法,該方法就是執行bean創建的方法,但是bean的創建過程非常複雜,並非如下這段代碼可以說的清楚的,這裏只是爲了解屬性裝配發生在什麼時候,所有bean的實例化過程不在此說明
我們可以看到在bean創建成功後,會調用populateBean(beanName, mbd, instanceWrapper);這樣一個方法,這個方法就是進行屬性裝配的方法
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
//首先從緩存中獲取,同時刪除緩存中的對象
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//獲取bean包裝實例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//申請合併BeanDefinition後置處理器
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//原來getSingleton()方法中earlySingletonObjects數據在這裏設置的
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//屬性添加,給實例對象填充屬性
populateBean(beanName, mbd, instanceWrapper);
//初始化bean, 也就是生命週期回到,@PostConstruct,InitializingBean SmartInitializingSingleton
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
//從單例池中獲取對象,如果單例池中不存在實例對象,
//那麼就從earlySingletonObjects中查找
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
//需要研究???似乎是解決循環依賴的
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
//註冊對象銷燬,對象銷燬時需要調用的方法也是很在這個地方進行註冊的(內部有方法需要好好看看)
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
問題:我們知道了@Autowire, @Value, @Inject由AutowiredAnnotationBeanPostProcessor處理,@Resource由CommonAnnotationBeanPostProcessor處理,spring是怎麼知道那些屬性需要進行裝配,又是如何還實現的?
要完成屬性裝配,首先我們需要解決的一個問題是要知道那些屬性需要裝配,這個時候最開始說到的那些註解已經那兩個類(@Resource, @Inject, @Autowire, @Value)[CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor]就要起作用了
那麼spring是如何查找這些需要裝配的屬性的呢?依舊查看上邊的這個方法doCreateBean();這個 方法中有applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);這樣一個方法調用,spring就是通過這裏後置處理器進行判斷的,查看看這個方法內部實現,方法內部調用了後置處理器的bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);方法,那麼在CommonAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor中這兩個方法的實現分別是?
首先Spring拿到類的所有屬性,然後查到這裏屬性上標註的註解,在與CommonAnnotationBeanPostProcessor/AutowiredAnnotationBeanPostProcessor中對應的註解比對,如果在後置處理中認定註解,那麼對應的這個屬性就需要進行屬性裝配
在AutowiredAnnotationBeanPostProcessor中判斷是,只要找到一個就立馬返回,無需後續在次判斷
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
//----------------------------------------------------------------------
//AutowiredAnnotationBeanPostProcessor
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//查找需要裝配的屬性元數據
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
//----------------------------------------------------------------------
//查找需要裝配的屬性元數據,最後查找出來的這些屬性會被放到injectionMetadataCache中,而在後續進行實際裝配時,也會從這裏邊查找需要的屬性名稱
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) {
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 -> {
//查找屬性上中標註的自動裝配註解,@Value, @Inject, @Autowire, 找到一個就會立即返回
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;
}
//判斷屬性裝配的必要性
//如:@Autowire(required=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))) {
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);
}
//----------------------------------------------------------------------
//查找屬性裝配註解,@Value, @Inject, @Autowire
//只要找到其中一個就立馬返回
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao, SearchStrategy.INHERITED_ANNOTATIONS);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
//
//
//
//CommonAnnotationBeanPostProcessor中屬性裝配元數據構建方法
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 -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
else if (field.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
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))) {
if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
}
else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static methods");
}
if (method.getParameterCount() != 1) {
throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
}
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new EjbRefElement(method, bridgedMethod, pd));
}
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
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);
}
問題:既然知道了哪些屬性需要進行裝配,那麼spring是如何拿到這些需要裝配的屬性值的,又是如何將他們裝配上的
終於到屬性裝配這一步了,我們看看populateBean()方法的實現,這個方法一般情況下前邊一大截都是沒用,因爲在一般情況下pvs都是空的,還有我們需要注意的是,在真正進行屬性裝配前,會執行InstantiationAwareBeanPostProcessor 後置處理器的postProcessAfterInstantiation()方法,如果我們想在自己實現某些特殊屬性裝配,這是spring爲我們提供一個拓展點,不過需要注意的是,這個方法需要返回ture,如果其中某一個後置處理器的該方法返回flase,那麼後續的裝配也就不會執行了
實際真正執行裝配工作也是通過後置處理器進行的,所有在spring中,後置處理器是一個非常重要的概念,基本所有的工作都是通過後置處理器完成。ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);這個InstantiationAwareBeanPostProcessor 後置處理器的方法調用就是完成裝配的核心,深入到這兩個後置處理器方法內部我們知道,獲取到metadata後執行inject()方法,完成屬性注入
根據代碼可以知道,@Resource通過名稱查找屬性值,而非@Resource的情況下,
* 首先從@Value推薦池中獲取
* 然後根據類型查找
* 如果根據類型能查找到多個值,那麼選擇Primary, 如果沒有或者存在多個Primary
* 則選這Priority,如果沒有或者存在多個最高,則在這些候選項中根據名稱查找
* 如果還是查不到,再根據名稱再重新獲取一遍
*
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* 進行bean屬性填充
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
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;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before beanfactorypostprocessor are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
//拿出所有的beanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//過濾InstantiationAwareBeanPostProcessor
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//如果其中一個執行結果返回false,後面的postProcessor就無需執行了
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//注意, spring要是沒有提供InstantiationAwareBeanPostProcessor,或者所提供的InstantiationAwareBeanPostProcessor
//postProcessAfterInstantiation方法都返回存在false,必須要保證所有的後置處理器都正常得到了執行,那麼說明後續無需繼續執行
//那麼就說明使用自定義的後置處理器進行屬性注入即可
if (!continueWithPropertyPopulation) {
return;
}
//拿出屬性
//已有的這些應該是通過BeanFactoryPostProcessor進行填充的
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//獲取自動注入模型/NO/ByName/ByType/ByConstructor/AutoDec
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
//通過名稱或者類型自動注入處理
//需要處理通過註解或者xml配置的部分
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//判斷是否存在InstantiationAwareBeanPostProcessors
//如果存在, 在對象銷燬時,會執行一些特殊的事情
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
//拿出所有的後置處理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//過濾出所有的InstantiationAwareBeanPostProcessor
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//執行後置處理器,對屬性進行操作
//這個方法可以更改這些屬性
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.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);
}
}
//-----------------------------------------------------------------
//CommonAnnotationBeanPostProcessor,進行屬性裝配的方法
//這裏的findResourceMetadata()就是之前我們分析獲取元數據的方法
@Override
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;
}
/**
* @Autowire, @Value, @Inject屬性裝配執行後置處理器方法
* AutowiredAnnotationBeanPostProcessor
* @param pvs
* @param bean
* @param beanName
* @return
*/
@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) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
//執行裝配
element.inject(target, beanName, pvs);
}
}
}
@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);
}
}
}
問題:都說@Resource()是根據名稱進行屬性注入,怎麼證明?
我們剛纔看了metadata.inject()方法,接着往這個方法深入,我們會找到autowireResource()這個方法的調用,這個方法內部resource = factory.getBean(name, element.lookupType);有這麼一段,證明了我們的問題
- resource = beanFactory.resolveBeanByName(name, descriptor);
/**
* Obtain a resource object for the given name and type through autowiring
* based on the given factory.
* @param factory the factory to autowire against
* @param element the descriptor for the annotated field/method
* @param requestingBeanName the name of the requesting bean
* @return the resource object (never {@code null})
* @throws NoSuchBeanDefinitionException if no corresponding target resource found
*/
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
throws NoSuchBeanDefinitionException {
Object resource;
Set<String> autowiredBeanNames;
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;
}
問題:@Autowire是使用類型注入?
都說@Autowire是首先按照類型查找,如果查到有多個候選項,判斷是否有Primary, 如果沒有判斷是否有優先級最大的,如果優先級都一樣,再按照名字查找,如果在多個候選項中根據名稱確定不了,還會通過名稱直接重新獲取一遍,如果還是查不到,但是有多個候選,那麼拋出有候選項不唯一的異常,如果找不到這種類型的bean,所以網上的說明都不完全,那麼如何證明呢,看源碼,其實這個說法還不完全,最先還要去查找@Value推薦池中能不能找到屬性,如果找不到才獲取bean
/**
* 獲取需要裝配的屬性值
* 首先從@Value推薦池中獲取
* 然後根據類型查找
* 如果根據類型能查找到多個值,那麼選擇Primary, 如果沒有或者存在多個Primary
* 則選這Priority,如果沒有或者存在多個最高,則在這些候選項中根據名稱查找
* 如果還是查不到,再根據名稱再重新獲取一遍
*
* 如果通過類型查找出多個,但是確定不了唯一,則會報不唯一異常
* 如果找不到一個符合條件的,則會報找不到異常
* @param descriptor
* @param beanName
* @param autowiredBeanNames
* @param typeConverter
* @return
* @throws BeansException
*/
@Nullable
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();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
//首先獲取@Vaule推薦值
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()));
}
}
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;
//存在多個候選項是,首先懸着Primary, 然後選擇最高權重,最後選擇名稱
if (matchingBeans.size() > 1) {
//判斷在存在多個候選項的時候,該選擇哪一個bean
//首先判斷Primary,如果沒有Primary或者存在多個Primary則繼續
// 判斷Priority,如果沒有或存在多個相同的Priority,返回
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
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);
}
}
/**
* Determine the autowire candidate in the given set of beans.
* 判斷在存在多個候選項的時候,該選擇哪一個bean
* 首先判斷Primary,如果沒有Primary或者存在多個Primary則繼續
* 判斷Priority,如果沒有或存在多個相同的Priority,返回
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
* @param candidates a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates}
* @param descriptor the target dependency to match against
* @return the name of the autowire candidate, or {@code null} if none found
*/
@Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {//存在多個候選項是,判斷是否有Primary存在
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;
}
問題:都在議論spring自動注入模型,那麼到底使用了那種注入模型?
spring默認不採用任何注入模型
public int getResolvedAutowireMode() {
if (this.autowireMode == AUTOWIRE_AUTODETECT) {
// Work out whether to apply setter autowiring or constructor autowiring.
// If it has a no-arg constructor it's deemed to be setter autowiring,
// otherwise we'll try constructor autowiring.
Constructor<?>[] constructors = getBeanClass().getConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterCount() == 0) {
return AUTOWIRE_BY_TYPE;
}
}
return AUTOWIRE_CONSTRUCTOR;
}
else {
//默認情況
//默認不採取自動注入
//private int autowireMode = AUTOWIRE_NO;
return this.autowireMode;
}
}