admin管理员组文章数量:1641815
文章目录
- 缘由
- 源码
- 在第三次后置处理器调用时的部分源码:
- 具体的实现
- 跟踪 公共的注解后置处理器解析:
- 或者是AutowiredAnnotationBeanPostProcessor:
- 那么如何类的注解信息源的?
- 以AutowiredAnnotationBeanPostProcessor为例:
- 结论
缘由
学习spring-IOC后置处理器的第三次调用发现一个有意思的点,所以写出来记录一下。
源码
在研究ioc的bean的创建过程,
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean:
在第三次后置处理器调用时的部分源码:
// Allow post-processors to modify the merged bean definition.
//允许后置处理器修改合并beanDefinition
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;
}
}
具体的实现
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
//全部转换成统一格式的BeanPostProcessor的子类MergedBeanDefinitionPostProcessor
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
//调用实际的后置处理方法
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
跟踪 公共的注解后置处理器解析:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//获取类的生命周期的信息,LifecycleMetadata包含初始化方法和销毁方法信息,将获取的类的初始化方法和销毁方法注册
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
//获取类的注解信息源数据
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
//注册
metadata.checkConfigMembers(beanDefinition);
}
或者是AutowiredAnnotationBeanPostProcessor:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
最终都是获取InjectionMetadata 。
那么如何类的注解信息源的?
CommonAnnotationBeanPostProcessor:负责解析@Resource、@WebServiceRef、@EJB三个注解
AutowiredAnnotationBeanPostProcessor:负责@Autowired
AutowiredAnnotationBeanPostProcessor:负责@Persistence
以AutowiredAnnotationBeanPostProcessor为例:
跟踪最终的代码:
/***
* 找到所要注入的类,标记有 @Autowired注解的 field和method 添加到一个list中
* 以list和这个class封装成一个InjectionMetadata
*/
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 -> {
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();
}
/***
* 一直循环封装,直到目标类为null或者父类是Object
* -->这里也就说明了如果你在一个子类有@AutoWired注解的 field和method,
* 那么会一直扫描父类,直到扫描到Object才停止
*/
while (targetClass != null && targetClass != Object.class);
//封装找到了的method和field,放到InjectionMetadata
return InjectionMetadata.forElements(elements, clazz);
}
结论
其他注解对应的后置处理器,我也基本跟了一遍最终都是一样的循环和判断条件。
根据while的条件,可知如果你在一个子类有@AutoWired,@Resource等注解修饰, 那么会一直扫描父类,直到扫描到Object才停止,最后将扫描的该类和该类的所有父类的注解放到list中,才会返回。
**最终结论:**spring是会把@autowired、@Resource这些注解注入的类的所有父类也注入进来。父类不用任何注解就可以被spring容器管理。如果子类用service注解了,父类也怼个service注解,当我们将父类用 @Autowired注入任何其他类的时候,就会报错。因为spring容器不知道该用子类引用的那个还是父类这个。这里可以采用@Component(value = “a”)指定父类的名称,然后用 @Resource(name = “a”) private T111111111 t111111111;注入就可以解决。
跟注解继承没关系,注解继承是 父类上的注解必须有被元注解@Inherited注解才行,这个是jdk搞的.
版权声明:本文标题:spring是会把@autowired注解注入的类的所有父类也注入进来。父类不用任何注解就可以被spring容器管理-源码底层告诉你 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1729330713a1196358.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论