本文是我的第一篇博客,自我研读spring源码以来,收获颇丰。自工作以来,疑惑颇多,于是通过网络、同事、领导、技术网友等益友的分享和指导,解决了工作中许多疑难杂症,所以我也非常希望把我工作中、学习中的收获分享给所有需要的人。同时受水平所限,其中必有缺漏不足之处,还望指出。
"道友"解释->志同道合者;
书山有路勤为径,学海无涯需持久!
源码阅读是一件枯燥乏味的事情,这种说法是对没有时间、没有兴趣、没有好奇心的道友来讲的。要想深入理解一个框架的原理,必须了解其实现细节,所以花费大量的时间、精力来吸取里面的营养是必须的。
<源码-spring>系列文章均涉及大量源码,且自建简单的项目是基于springboot 2的版本,如果其他版本的源码可能稍有差异,属正常情况。
如果道友你从来没有看过spring源码,阅读起来将会吃力,请悉知!
本文核心讲解的是@Bean注解从解析bean到beanFactory的beanDefiniton中
package org.springframework.context.annotation;
当spring启动后,走到高级AbstractApplicationContext这个高级容器的最核心的 refresh() 方法后,再进入invokeBeanFactoryPostProcessors(beanFactory)调用后置处理器方法,就会调用静态方法PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()) 开始解析所有的BeanDefinition了,由于本文主要讲解@Bean,所以其他的暂时不详解。
//此类就是解析配置类的入口
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//先判断是否有@Component注解,
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
//首先递归处理任何成员(嵌套)类
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
//处理带有@PropertySource的类,然后将里面变量存到全局的Environment中去
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理 @ComponentScan 注解,注意里面是多个递归解析(如果不清楚是递归的道友进入这个方法可能会晕掉的),这
//里面就会解析所有的@Component注解的,包括@Controller、@Service等这些被@Component注解过的注解,解析后的
//bean全部放到ConfigurationClassParser这个对象的 configurationClasses 这个map里面进行后续处理
Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
//处理@Import的注解
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 关键来了,本文重点就是分析 @Bean的解析过程,。先获取被@Bean了的方法,下面会讲解此方法
Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
//然后把@Bean注解的方法放入到 ConfigurationClass 这个对象里面的 beanMethods这个/Set 里面
//到此,解析@Bean的bean第一步-先把@Bean找出来,就在这完成了,下面会简单说一下装@Bean的类BeanMethod
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
此方法是获取当前类所有的@Bean注解的方法
//此方法是检索所有@Bean方法的元数据
private Set retrieveBeanMethodMetadata(SourceClass sourceClass) {
//获取元数据信息
AnnotationMetadata original = sourceClass.getMetadata();
//获取所有的@Bean方法
Set beanMethods = original.getAnnotatedMethods(Bean.class.getName());
if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
//尝试通过ASM读取类文件以确定性声明顺序... 不幸的是,JVM的标准反射以任意//顺序返回方法,甚至在同一JVM上
//同一应用程序的不同运行之间。
try {
AnnotationMetadata asm =
this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
Set asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
if (asmMethods.size() >= beanMethods.size()) {
Set selectedMethods = new LinkedHashSet<>(asmMethods.size());
for (MethodMetadata asmMethod : asmMethods) {
for (MethodMetadata beanMethod : beanMethods) {
if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
selectedMethods.add(beanMethod);
break;
}
}
}
if (selectedMethods.size() == beanMethods.size()) {
// All reflection-detected methods found in ASM method set -> proceed
beanMethods = selectedMethods;
}
}
}
catch (IOException ex) {
logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
// No worries, let's continue with the reflection metadata we started with...
}
}
return beanMethods;
}
以上操作就会把所有的@Bean方法找出来
package org.springframework.context.annotation;
上面的源码中,看见new BeanMethod(),这个BeanMethod继承了ConfigurationMethod类,ConfigurationMethod它有两个字段MethodMetadata和ConfigurationClass这两个对象,而BeanMethod集成后没有单独的字段,仅仅覆写了validate此方法和有一个私有的非静态的内部类,
final class BeanMethod extends ConfigurationMethod {
public BeanMethod(MethodMetadata metadata, ConfigurationClass configurationClass) {
super(metadata, configurationClass);
}
@Override
public void validate(ProblemReporter problemReporter) {
if (getMetadata().isStatic()) {
// static @Bean methods have no constraints to validate -> return immediately
return;
}
if (this.configurationClass.getMetadata().isAnnotated(Configuration.class.getName())) {
if (!getMetadata().isOverridable()) {
// instance @Bean methods within @Configuration classes must be overridable to accommodate CGLIB
problemReporter.error(new NonOverridableMethodError());
}
}
}
//这个BeanMethod.NonOverridableMethodError内部类的作用仅仅是处理@Bean方法 “ must not be private or final ”
private class NonOverridableMethodError extends Problem {
public NonOverridableMethodError() {
super(String.format("@Bean method '%s' must not be private or final; change the method's modifiers to continue",
getMetadata().getMethodName()), getResourceLocation());
}
}
}
上面将bean解析成ConfigurationClass后,接下来就需要把ConfigurationClass里面的beanMethods注册成为ConfigurationClassBeanDefinition
package org.springframework.context.annotation;
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
//判断是否需要跳过注册
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
//如果是
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//此方法就是把@Bean注册到beanFactory的入口
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//这里面处理实现了ImportBeanDefinitionRegistrar的类,此时会调用ImportBeanDefinitionRegistrar的registerBeanDefinitions方法
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
//获取@Bean方法的类的信息
ConfigurationClass configClass = beanMethod.getConfigurationClass();
//获取@Bean的元数据信息
MethodMetadata metadata = beanMethod.getMetadata();
//获取方法名,也就是默认的bean的名称
String methodName = metadata.getMethodName();
// 我们是否需要将bean标记为跳过它的状态
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
if (configClass.skippedBeanMethods.contains(methodName)) {
return;
}
//把@Bean注解里面的信息解析出来
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
Assert.state(bean != null, "No @Bean annotation attributes");
// 取出别名
List names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
// 将别名注册到beanFactory
for (String alias : names) {
this.registry.registerAlias(beanName, alias);
}
if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
"' clashes with bean name for containing configuration class; please make those names unique!");
}
return;
}
//ConfigurationClassBeanDefinition它是ConfigurationClassBeanDefinitionReader的内部的私有的静态类
//ConfigurationClassBeanDefinition它继承了RootBeanDefinition,RootBeanDefinition的层级关系这里就不罗列了哈
//为什么要用ConfigurationClassBeanDefinition把bean信息包装一层? 因为beanFactory的beanDefinitionMap必须是BeanDefinition的子类
//实现了它才是标准的BeanDefinition,spring实例化bean只能实例化BeanDefinition
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
beanDef.setResource(configClass.getResource());
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
//静态的@Bean和非静态的处理方式有一点点区别
if (metadata.isStatic()) {
// 静态 @Bean 方法,这里设置的是setBeanClassName
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}
else {
// 实例 @Bean 方法setFactoryBeanName
beanDef.setFactoryBeanName(configClass.getBeanName());
beanDef.setUniqueFactoryMethodName(methodName);
}
//下面都是设置@Bean注解里面属性
beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
Autowire autowire = bean.getEnum("autowire");
if (autowire.isAutowire()) {
beanDef.setAutowireMode(autowire.value());
}
boolean autowireCandidate = bean.getBoolean("autowireCandidate");
if (!autowireCandidate) {
beanDef.setAutowireCandidate(false);
}
String initMethodName = bean.getString("initMethod");
if (StringUtils.hasText(initMethodName)) {
beanDef.setInitMethodName(initMethodName);
}
String destroyMethodName = bean.getString("destroyMethod");
beanDef.setDestroyMethodName(destroyMethodName);
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
if (attributes != null) {
beanDef.setScope(attributes.getString("value"));
proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = ScopedProxyMode.NO;
}
}
// 如有必要,将原始bean定义替换为目标bean定义
BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry,
proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
if (logger.isTraceEnabled()) {
logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
configClass.getMetadata().getClassName(), beanName));
}
//这里调用了真正的、幕后的BeanFactory->DefaultListableBeanFactory的registerBeanDefinition方法,下面继续看源码
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
package org.springframework.beans.factory.support;
躲在层层包装之后的beanFactory就是它了,spring的beanFactory的核心类之一,DefaultListableBeanFactory
//这个方法是BeanDefinitionRegistry接口的实现
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//老规矩,先验证合法性
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
//如果beanDefinitionMap已经存在了,就验证是否两个对象相同然后打印一下废话日志等等,反正最后要把它给覆盖了,哈哈哈
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//管你已经占着茅坑在拉屎,现在我是老大一脚把你踢开让我来,哈哈哈哈
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//检查此工厂的bean创建阶段是否已经开始,即是否在此期间将任何bean标记为已创建,说白了就是
//目前为止 IOC 容器已经有病了(有bean),哈哈哈
//这里为什么要整一个判断 IOC 容器是否已经启动了呢????
//情况成员变量: private volatile List beanDefinitionNames = new ArrayList<>(256);
//明白了没? size = 256 !!! 如果容器已经启动了,那么有可能 beanDefinitionNames已经满了,装不下了,数组越界,所以
//需要新建一个数组,容量加一个,然后重新引用。。。。
if (hasBeanCreationStarted()) {
// 无法再修改启动时集合元素(用于稳定迭代),这里就最终的开始将@Bean的bean注册到beanDefinitionMap了
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
//上面说的list容量加一,就是这里哈
List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
//仍在启动注册阶段,意思就是目前为止 IOC 没病(bean),容器还是空的
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDe finition(beanName);
}
}
至此,@Bean的bean从配置类里面已经成功从一个小妹妹变成了一个大菇凉了。
spring在启动时,在调用后置处理器PostProcessor的时候,将会把所有的bean包括@Bean的bean注册到beanFactory的beanDefiniton里面去,先将@Bean解析到父ConfigurationClass里面去,然后再一个一个的加载ConfigurationClass里面的bean定义。最后再告诉道友一个小秘密哦,这里面的所有操作都在 ConfigurationClassPostProcessor 这个 PostProcessor里面的invokeBeanDefinitionRegistryPostProcessors静态方法里面完成的,哈哈哈哈