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真的是一应俱全