Spring IoC 公共注解详解
2021-04-23 18:28
标签:简单 anti def 初始化 sso 基本 hub getbean org 本系列全部基于 什么是公共注解?公共注解就是常见的Java注解,特别是JSR-250中的注解。例如: 对 关于 上面代码中的 注意:静态字段和静态方法会过滤掉。 上面的 上面 从上面的代码也可以看出一般情况下 处理 上面代码中的 这里我们简单看一下 看到这里我们知道为什么标注了 我们先了解一下 和上面的 本文主要介绍了 最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring。 Spring IoC 公共注解详解 标签:简单 anti def 初始化 sso 基本 hub getbean org 原文地址:https://www.cnblogs.com/leisurexi/p/13269643.html前言
Spring 5.2.2.BUILD-SNAPSHOT
版本。因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析。@Resource
、@PostConstructor
、@PreDestroy
等等,本文也就主要分析这三个注解在 Spring 中是如何处理的。正文
@Resource 注解的处理
@Resource
注解的处理类是 CommonAnnotationBeanPostProcessor
,它通过实现 InstantiationAwareBeanPostProcessor
接口,重写 postProcessProperties()
方法实现对标注了 @Resource
注解的字段或方法的自动注入。
InstantiationAwareBeanPostProcessor
接口的详细信息可以查看Spring IoC bean 的创建。CommonAnnotationBeanPostProcessor
这个后置处理器是怎么加入到 beanFactory
中的,我们在 Spring IoC component-scan 节点详解 一文中介绍过主要是通过 AnnotationConfigUtils#registerAnnotationConfigProcessors()
实现的。public static Set
BeanDefinition 合并后的后置处理
CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// 寻找需要注入的字段或方法,并封装成 InjectionMetadata
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
// 检查元数据中的注解信息
metadata.checkConfigMembers(beanDefinition);
}
findAutowiringMetadata()
方法就是利用反射遍历类的所有字段和方法,找到标注了 @Resource
注解的,并缓存进 injectionMetadataCache
中。
findAutowiringMetadata()
方法基本和 AutowiredAnnotationBeanPostProcessor
中的一致,只是处理的注解不同而已,可以查查看Spring IoC @Autowired 注解详解一文中该方法的详解。bean 属性后置处理
CommonAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 从injectionMetadataCache缓存中获取需要注入的字段和方法
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;
}
// InjectMetadata.java
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
// 获取检查后的元素
Collection
元素注入
InjectionMetadata#inject
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
throws Throwable {
// 如果元素是字段
if (this.isField) {
// 强转成Field类型
Field field = (Field) this.member;
// 并设置为可访问
ReflectionUtils.makeAccessible(field);
// 然后使用反射设置值
field.set(target, getResourceToInject(target, requestingBeanName));
}
else {
// 检查是否跳过
if (checkPropertySkipping(pvs)) {
return;
}
try {
// 强转成Method类型
Method method = (Method) this.member;
// 并设置为可访问
ReflectionUtils.makeAccessible(method);
// 使用反射调用方法
method.invoke(target, getResourceToInject(target, requestingBeanName));
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
获取注入资源
ResourceElement#getResourceToInject
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) : getResource(this, requestingBeanName));
}
lazyLookup
就是是否在属性或方法上标注了 @Lazy
注解,该注解先暂不讨论,所以调用后面的 getResource()
方法。CommonAnnotationBeanPostProcessor#getResource
protected Object getResource(LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException {
// 省略其它代码...
return autowireResource(this.resourceFactory, element, requestingBeanName);
}
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException {
Object resource;
Set
autowireResource()
方法中按类型查找的 resolveDependency()
方法在Spring IoC bean 的创建一文中分析过,按名称查找 bean
的 resolveBeanByName()
方法实际就是调用 getBean()
通过名称和类型去获取 bean
。
@Resource
注解是按名称注入;而 @Autowired
注解时按类型注入,具体可以查看Spring IoC @Autowired 注解详解。@PostConstruct、@PreDestroy 注解的处理
@PostConstruct
和 @PreDestroy
注解的处理类是 InitDestroyAnnotationBeanPostProcessor
,CommonAnnotationBeanPostProcessor
继承与该类,相当于注册 CommonAnnotationBeanPostProcessor
时也注册了 InitDestroyAnnotationBeanPostProcessor
。BeanDefinition 合并后的后置处理
InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()
方法是通过 CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition()
方法调用的,如下:CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
// 调用InitDestroyAnnotationBeanPostProcessor的postProcessMergedBeanDefinition()方法
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// 寻找需要注入的字段或方法,并封装成 InjectionMetadata
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
// 检查元数据中的注解信息
metadata.checkConfigMembers(beanDefinition);
}
InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
// 寻找需要标注了@PostConstruct和@PreDestroy注解的方法,并封装进LifecycleMetadata
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
// 检查元数据中的注解信息
metadata.checkConfigMembers(beanDefinition);
}
findLifecycleMetadata()
方法,就是遍历当前初始化的 bean
包括其父类中所有标注了 @PostConstruct
和 @PreDestroy
注解的方法,并封装成 LifecycleMetadata
(该类是 InitDestroyAnnotationBeanPostProcessor
中一个内部类),并放入 lifecycleMetadataCache
缓存中。LifecycleMetadata
这个类:private class LifecycleMetadata {
// 目标类,也就是当前正在初始化的bean
private final Class> targetClass;
// 存放标注了@PostConstruct的方法
private final Collection
bean 的初始化前回调
InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 从lifecycleMetadataCache缓存中获取LifecycleMetadata
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 反射调用所有初始化方法
metadata.invokeInitMethods(bean, beanName);
}
// 省略异常处理...
return bean;
}
@PostConstruct
注解的方法比 InitializingBean#afterPropertiesSet()
方法和自定义初始化方法先调用了;因为其在 bean
的初始化前回调就已经调用了,而剩下的两个是在初始化方法中调用的,详情可以查看Spring IoC bean 的初始化一文。bean 销毁前回调
DestructionAwareBeanPostProcessor
,它继承自 BeanPostProcessor
,如下:public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
/**
* Bean 销毁前阶段回调
*/
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
/**
* bean实例是否要由此方法销毁
*/
default boolean requiresDestruction(Object bean) {
return true;
}
}
InitDestroyAnnotationBeanPostProcessor#postProcessBeforeDestruction
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
// 从lifecycleMetadataCache缓存中获取LifecycleMetadata
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 反射调用所有销毁方法
metadata.invokeDestroyMethods(bean, beanName);
}
// 省略异常处理...
}
@PostConstruct
注解一样,@PreDestroy
注解标注的方法也比 DisposableBean#destroy()
方法和自定义销毁方法先调用。总结
@Resource
、@PostConstruct
、@PreDestroy
注解 Spring 是如何对其处理的,可以看出 Spring 的注解驱动大多依靠 实现 BeanPostProcessor
及其子类中的 bean
生命周期各个阶段的回调方法来进行实现的。