0. 举个栗子:
本版本源码为SpringBoot - 2.3.3.RELEASE,即spring-beans: 5.2.8.RELEASE
·
主要通过学习@Autowired注入过程来学习Bean创建生命周期
·
主要源码入口:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
@Component
public class SetterBean {
@Autowired
private BeanService beanService;
}
@Configuration
public class ConfigurationBean {
@Bean
public BeanService beanService() {
BeanServiceImpl beanService = new BeanServiceImpl();
beanService.setName("zhangsan");
return beanService;
}
}
在createBeanInstance创建bean实例后(该方法简要可参考createBeanInstance基本功能)
·
会应用applyMergedBeanDefinitionPostProcessors
这个后置处理器,去收集/预解析属性元数据
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
... ... ... ...
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
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;
}
}
... ... ... ...
}
1. applyMergedBeanDefinitionPostProcessors:
这个方法本质就是调用MergedBeanDefinitionPostProcessor接口实现类的
postProcessMergedBeanDefinition
方法
·
通过该方法去收集类中指定注解的属性元数据,这里主要分析AutowiredAnnotationBeanPostProcessor
- AutowiredAnnotationBeanPostProcessor 支持@Autowired,@Value注解
- CommonAnnotationBeanPostProcessor 支持@PostConstruct,@PreDestroy,@Resource注解
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
1.1. AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:
主要通过findAutowiringMetadata方法去收集@Autowired,@Value注解的属性元数据
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
1.1.1. findAutowiringMetadata:
先从缓存中查找有没有要注入的属性元数据对象InjectionMetadata,有则直接返回
缓存没有,则经过双重校验后,去构建要注入属性的元数据;构建成功写入缓存
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 先从缓存中查找有没有要注入的属性元数据,有则直接返回
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 经过双重校验后,去构建要注入属性的元数据
metadata = buildAutowiringMetadata(clazz);
// 构建完写入缓存
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
1.1.2. buildAutowiringMetadata:
通过循环遍历类属性和方法,查找出指定注解注释的属性和方法,
属性封装到AutowiredFieldElement,方法封装到AutowiredMethodElement,最后都封装到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 -> {
// 循环遍历类属性,找到@Autowired,@Value注解的属性
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
if (ann != null) {
// 判断该属性是否是static修饰的,是的话则直接返回,可能导致该属性后续无法注入
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 判断属性是否是必须的,除非显示指定非必须@Autowired(required = false),默认是true
boolean required = determineRequiredStatus(ann);
// 找到指定注解的属性,封装成AutowiredFieldElement,然后添加到currElements
currElements.add(new AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// 循环遍历类方法,找到@Autowired,@Value注解的方法
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// 判断该方法是否是static修饰的,是的话则直接返回
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);
}
}
// 判断方法是否是必须的,除非显示指定非必须@Autowired(required = false),默认是true
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 找到指定注解的方法,封装成AutowiredMethodElement,然后添加到currElements
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);
}
1.1.3. ReflectionUtils#doWithLocalFields:
和doWithLocalMethods方法一样,第二个参数是函数式接口
- 循环遍历类属性,执行fc.doWith(field);,会触发回调函数方法
- 在findAutowiredAnnotation方法查找该属性,是否被@Autowired,@Value注解
这类函数式接口回调,在spring源码中很常见,也是很妙(doge)
public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
for (Field field : getDeclaredFields(clazz)) {
try {
fc.doWith(field);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
}
}
}
1.1.4. populateBean:
收集完的属性,会在属性填充方法populateBean里面进行依赖注入,本方法代码后续再详细介绍
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
... ... ...
try {
populateBean(beanName, mbd, instanceWrapper);
... ... ...
通过AutowiredAnnotationBeanPostProcessor#postProcessProperties方法,进行属性注入
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
... ... ...
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 新版本调用postProcessProperties来进行依赖注入
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 兼容旧版本使用postProcessPropertyValues依赖注入
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
... ... ...
上述
applyMergedBeanDefinitionPostProcessors
中已经完成属性元数据的预解析,所以能直接获取封装好的属性元数据数据
@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;
}
关于属性填充和注入的详情,可查看文章:属性填充populateBean | 静态属性注入
1.1.5. 小结:
在createBeanInstance创建bean实例后(该方法简要可参考createBeanInstance基本功能)
·
会应用applyMergedBeanDefinitionPostProcessors
这个后置处理器,去收集/预解析属性元数据
·
通过循环遍历类属性和方法,找到有指定注解的属性,封装到注入元数据对象InjectionMetadata
·
在属性填充populateBean时,从缓存中获取InjectionMetadata,进行注入
1.2. CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:
改方法会收集@PostConstruct 、@Resource的元数据信息
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 调用父类方法收集@PostConstruct元数据信息
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
// 通过findResourceMetadata方法去收集@Resource注解的属性元数据
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
1.2.1. findResourceMetadata:
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// 先从缓存中查找有没有要注入的属性元数据,有则直接返回
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
// 经过双重校验后,去构建标注@Resource属性的元数据
metadata = buildResourceMetadata(clazz);
// 构建完写入缓存,方便调用获取,防止重复解析
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
1.2.2. buildResourceMetadata:
通过循环遍历类属性和方法,查找出@Resource注解注释的属性和方法,
都属性封装到ResourceElement,最后都封装到InjectionMetadata返回
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
}
currElements.add(new WebServiceRefElement(field, field, null));
}
else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@EJB annotation is not supported on static fields");
}
currElements.add(new EjbRefElement(field, field, null));
}
// 上面的判断是处理EJB和WebServiceRef,反正我没用过也不晓得
// 下面才是判断属性是不是@Resource标注的
else if (field.isAnnotationPresent(Resource.class)) {
// 判断该属性是否是static修饰的,是的话抛异常
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static fields");
}
// 属性不是static修饰的,判断属性类型是不是javax.xml.ws.WebServiceContext
// CommonAnnotationBeanPostProcessor初始化时会将WebServiceContext添加到ignoredResourceTypes
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
// 条件符合,将属性封装成ResourceElement,再添加到currElements
// ResourceElement构造函数会对member、name等进行赋值
currElements.add(new ResourceElement(field, field, null));
}
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 获取桥接方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
// 比较目标方法和桥接方法是不是一致(类型、参数、参数类型俊一致,不一致返回)
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
// 通常桥接方法都是一致的,反正我也不懂桥接方法是上面鬼
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
... ... ... // 省略EJB、webServiceRef的封装逻辑
else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
// 同样判断方法是不是static修饰的,是就抛异常
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalStateException("@Resource annotation is not supported on static methods");
}
Class<?>[] paramTypes = method.getParameterTypes();
// 获取注解方法的参数类型数组,即无参数或多个参数则抛异常
if (paramTypes.length != 1) {
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
}
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
// 找到指定注解的方法,封装成ResourceElement,然后添加到currElements
currElements.add(new ResourceElement(method, bridgedMethod, pd));
}
}
}
});
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return InjectionMetadata.forElements(elements, clazz);
}
1.2.3. ResourceElement:
再这个构造函数里,这里会获取注解的属性值进行赋值(比如name)
public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
// 会将属性(field)赋予内部属性member,还有方法类属性描述器赋值
super(member, pd);
Resource resource = ae.getAnnotation(Resource.class);
// 获取@Resource(name = "beanService1")的name属性值;标注在方法的注解,则为方法名
String resourceName = resource.name();
// 获取@Resource(type = BeanService.class)的type属性值,默认Object类型
Class<?> resourceType = resource.type();
// 注解写了name,即resourceName非空,则isDefaultName=false
this.isDefaultName = !StringUtils.hasLength(resourceName);
if (this.isDefaultName) {
// 注解不配置name,取要注入的属性的name
resourceName = this.member.getName();
// 处理方法上加注解的,方法名以set开头
if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
// 处理resourceName:截断set、转换首字母小写、连续大写则保留
// 如:setAbcResource --> abcResource ; setABCResource --> ABCResource
resourceName = Introspector.decapitalize(resourceName.substring(3));
}
}
else if (embeddedValueResolver != null) {
resourceName = embeddedValueResolver.resolveStringValue(resourceName);
}
// 不指定type属性,默认不成立,否则取检查指定的属性类型符不符合要注入的属性类型
if (Object.class != resourceType) {
checkResourceType(resourceType);
}
else {
// 不指定type,默认取要注入的属性类型
resourceType = getResourceType();
}
// 内部属性name、lookupType赋值
this.name = (resourceName != null ? resourceName : "");
this.lookupType = resourceType;
// 获取@Resource(lookup = "beanService1")的lookup属性值,并赋值mappedName,默认是“”
String lookupValue = resource.lookup();
this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
Lazy lazy = ae.getAnnotation(Lazy.class);
// 属性或方法还标注有@Lazy,则lazyLookup=true,默认false
this.lazyLookup = (lazy != null && lazy.value());
}
关于@Resource的后续调用可查看:文章4.5节内容
1.3. InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:
和@Resource一样,这里会去收集@PostConstruct的方法元数据,主要通过findLifecycleMetadata取封装
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
}
1.3.1. findLifecycleMetadata:
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
return buildLifecycleMetadata(clazz);
}
// 先从缓存中查找有没有要注入的方法元数据,有则直接返回
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
// 经过双重校验后,去构建标注@PostConstruct方法的元数据
metadata = buildLifecycleMetadata(clazz);
// 构建完写入缓存,方便调用获取,防止重复解析
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
1.3.2. buildLifecycleMetadata:
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
return this.emptyLifecycleMetadata;
}
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
// 循环遍历类的方法,找到@PostConstruct标注的方法
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
// 找到了@PostConstruct标注的方法,封装到LifecycleElement,再add进currInitMethods
currInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
// 和上面一样,这里是处理@PreDestory的,感觉少用不管他了
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (logger.isTraceEnabled()) {
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
// 最终封装到initMethods
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
// 如果两个集合都是空,就返回空对象emptyLifecycleMetadata,否则封装到LifecycleMetadata
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
1.3.3. LifecycleElement:
public LifecycleElement(Method method) {
// 注解的方法是无参或多个参数则抛异常
if (method.getParameterCount() != 0) {
throw new IllegalStateException("Lifecycle method annotation requires a no-arg method: " + method);
}
this.method = method;
// 注解的方法是private修饰的,则identifier为方法完全限定名,否则就只有方法名
this.identifier = (Modifier.isPrivate(method.getModifiers()) ?
ClassUtils.getQualifiedMethodName(method) : method.getName());
}
关于@PostConstruct的后续调用可查看:文章4.6节内容