我們先來寫一個簡單的demo方便debug調試。
public class QualifierDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();
applicationContext.register(QualifierDemo.class);
applicationContext.refresh();
applicationContext.close();
}
@Autowired
private User user;
@Bean
public User user(){
return createUser("user1");
}
private static User createUser(String name){
User user=new User();
user.setName(name);
return user;
}
}
首先我們來關注這個方法AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition,這個類實現了BeanPostProcessor的子接口,所以bean在實例化的時候會執行到這個方法。
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//獲取加了@Autowired的元信息數據
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
//將beanDefinition里Autowired相關信息添加到checkedElements里面,后面會用到。
metadata.checkConfigMembers(beanDefinition);
}
我們可以看到上面這個方法到入參里有個beanDefinition,這個beanDefinition正是QualifierDemo的實例,然后通過findAutowiringMetadata方法會去找關於Autowired的元信息。
這個方法執行完后,會執行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;
}
這里面關鍵的方法就是inject方法,他的代碼如下:
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//取之前存入的checkedElements
Collection<InjectedElement> checkedElements = this.checkedElements;
//沒有的話就取injectedElements,也是之前存入的
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
//遍歷@Autowired注解標記了的元信息數據集合,我們的示例中只有一個@Autowired User
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
//element正是我們示例代碼里的User的一些描述
element.inject(target, beanName, pvs);
}
}
}
element的結構圖如下:
可以看出,這個類型就是我們的User。接着往下看element#inject方法。
@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 {
//根據元信息描述去進行bean查找
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;
}
}
}
//將查找到的bean通過反射set到對象中及示例中的 @Autowired private User user;
if (value != null) {
//反射操作給private屬性需要的操作。
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
通過反射將查找到到bean注入到@Autowired注解到變量上。
另外,源碼中分析要經過的兩個方法postProcessMergedBeanDefinition和postProcessProperties,他們是因為實現了spring的接口,所以會被調用到。下面我們寫個例子證實它。
@Configuration
public class BeanPostConfig implements MergedBeanDefinitionPostProcessor, InstantiationAwareBeanPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
System.out.println("postProcessMergedBeanDefinition:"+beanName);
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
System.out.println("postProcessProperties:"+beanName);
return pvs;
}
}
打印結果如下:
postProcessMergedBeanDefinition:qualifierDemo
postProcessMergedBeanDefinition:user
postProcessProperties:user
postProcessProperties:qualifierDemo
事實證明實現了接口后,兩個方法都被執行了,並且會將postProcessMergedBeanDefinition方法執行完之后才開始調用postProcessProperties方法。