git: github.com/fw103699437…html
隔離在家,閒的蛋疼,正好有空梳理一下項目裏的代碼,就是所謂的重構羅,可是呢,我很顯然沒有相關的經驗和知識,就是想把一些java裏的繼承之類的、設計模式之類的給用上。
可是因爲spring的存在,有些東西沒法很方便的弄到spring中來,不少時候須要驗證。
例如一個接口的多個實現,有一些重複代碼,確定是要提出來,我將他提到一個抽象類裏。
那麼問題來了,抽象類沒法實例化,那麼也就沒法放入到spring容器中,可是抽象類中又要注入一個Bean。
按照個人理解java
百度獲得結果以下:git
說實話,有點get不到點,protected還有這麼神奇的功效?github
咱們寫一個簡單的例子好了,如圖所示:
spring
@RestController
public class Controller {
@Qualifier("impl1")
// @Qualifier("impl2")
@Autowired
Service service;
public void save(){
service.save();
}
}
複製代碼
通過實驗能夠發現,用@Qualifier指定不一樣實現時,子類的bean中會注入Dao,不會有問題。編程
getBean(beanName=controller)
而後注入屬性 populateBean(beanName=controller)
爲Controller注入beanName=imp1的bean設計模式
getBean(beanName=imp1) 利用AutowiredAnnotationBeanPostProcessor爲imp1尋找須要被注入的屬性post
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<>();
//這裏找到須要注入的field
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);
return InjectionMetadata.forElements(elements, clazz);
}
複製代碼
其中while (targetClass != null && targetClass != Object.class)這一句,先是在 ServiceImp1中須要要注入的field,沒有找到,而後在父類AbstractService中尋找,利用getDeclaredFields(clazz)找到了field(也就是dao)ui
而後根據findAutowiredAnnotation,找到了field上的註解@Autowired,肯定要注入父類中的Daothis
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
複製代碼
具體注入過程就不分析了。
子類交給spring容器,父類不交給spring容器,父類中的field也能夠完成自動注入
1:百度的結果中所說的protected,實際上是由private(或者default)改過來的,目的只是讓子類可以訪問到而已。(第一篇文章中從default改成protected,其實子類也在同一個包下時default就夠用。所以其實仍是有那麼一絲誤導,沒有說的太透徹。)
其中MergedBeanDefinitionPostProcessor的接口postProcessMergedBeanDefinition的實現,負責找到須要注入的屬性
InstantiationAwareBeanPostProcessor的接口postProcessProperties負責真正注入。
BeanPostProcessor真的是一應俱全