首先说一下关于Spring的源码,花了很久的时间、不停的反复查看资料和手写笔记以及总结、还只是明白了Spring源码当中的一小部分、最后总结出来一句话就是:Spring的源码 真的真的真的 很难读 Spring内部之间维护的关系,Spring大师写代码的思维逻辑,如果没有人引导你的话,你可能会掉进这个Spring的深渊,让你在这个深渊里面越陷越深(让你在Spring源码里面不停的绕,思维卡带,代码逻辑整理不顺,一行代码卡几天,等等)、你需要帮助才能从中脱离出来,你需要翻阅大量的资料、以及需要别人的帮助才能从里面走出来,然后继续跳下一个坑,当然 当你读懂了Spring的源码后你会无比的兴奋、你会发现Spring的魅力 ----->>>>> 反正一句话:Spring牛逼。下面所说的源码知识可能并不完全,后续更新知识会继续填充进去,尽量保证这个源码解析是比较全面的。
以下只是按照前辈的指导进行的总结,需要大量的意见以及改进。
我们先看这个类里面做了什么事情
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
首先来解析这一行代码中,Spring做了什么事情。
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
1.点开源码后显示的是这一段代码 - this();表示调用当前类的构造方法、但是我们往上看类的信息时可以看到当前类继承了一个名叫GenericApplicationContext
的类
public class AnnotationConfigApplicationContext extends GenericApplicationContext .... {
那么这个时候我们都知道,如果当前类继承了一个父类,那么调用构造方法时会先去调用父类的构造方法,下面我们看父类的构造方法做了什么事情。
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
通过作者的注释描述可以得知,这个位置是创建一个Spring的环境、在创建的Spring环境
中创建一个BeanFactory(Bean工厂)、BeanFactory是用来管理Bean的创建 —>>> 总结就是 Spring环境中创建了一个BeanFactory,或者说Spring环境中维护了一个BeanFactory(Bean工厂)。
然后回到AnnotationConfigApplicationContext类
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
在该类中定义了上图中的两个对象、我们来一个个的进行分析。
this.reader = new AnnotatedBeanDefinitionReader(this);
2我们可以看到在创建AnnotatedBeanDefinitionReader
对象时传入的参数为this,也就说明这个对象内部接收的参数是我们的当前类,也就是AnnotationConfigApplicationContext
类,下面我们看AnnotatedBeanDefinitionReader
在创建时做了什么事情。
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
3.可以看到AnnotatedBeanDefinitionReader
接收参数的类型居然是BeanDefinitionRegistry
类,而并不是我们以为的AnnotationConfigApplicationContext
类,我们可以想一下 这两个类是不是相等的、又或者说这个Spring环境中本身就维护着一个BeanDefinitionRegistry
类
我们先来看看BeanDefinitionRegistry
类名字的定义、BeanDefinition的注册器、我们找一下Spring当中是否有BeanDefinition这个类或者接口
/**
* A BeanDefinition describes a bean instance which has property values,
* constructor argument values, and further information supplied by
* concrete implementations.
*/
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
作者在注释中描述的大意为:BeanDefinition描述了一个bean实例,它具有属性值,构造函数参数值以及具体实现提供的更多信息。
可以得知BeanDefinition是用来描述Bean的(Bean的名字、Bean的所在类、Bean的作用域、Bean是否开启懒加载、等等)
我们在回到上面的2.的图 图中显示调用了this();我们看this();是跳向哪个地方
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
前面代码只是做一个校验、我们重点看最后一行代码AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
继续跳向下一段代码
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//现在要对工厂进行注册、所以要先得到环境内的工厂
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
//填充DependencyComparator参数、该参数是可以操控Bean初始化顺序的一个属性
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//填充AutowireCandidateResolver参数、该参数是可以处理延迟加载的一个属性
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//以下判断是Spring内部把需要的类转换成BD、然后进行注册
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//BeanDefinition的实现类、给Spring内部用来转换DB的类
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
//将注册器、Spring内部的BD以及Spring内部的表示传入到后置的注册器中
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
由于上图的代码较多 在代码中做了一些注释、这里在进行总结下:得到BeanFactory然后将Spring内部的类通过实现了BeanDefinition(简称BD)的实现类RootBeanDefinition通过实现类的构造方法将类进行BD的转换、然后把他们放进了一个registerPostProcessor
方法、最后在添加到上面定义的Set当中。我们来看registerPostProcessor
这个方法做了什么事。
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
方法内部接收一个BD的注册器、一个用实现了BeanDefinition的实现类RootBeanDefinition通过实现类的构造方法将类转换成的BD、还有一个名称(Spring内部定义的名称、也可以称为标记、毕竟只有Spring才知道)。然后又调用registry.registerBeanDefinition(beanName, definition);
我们继续跳进方法看。
public interface BeanDefinitionRegistry extends AliasRegistry {
该方法是个接口、我们来找他的实现类 —>>
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
可以得知 BeanFactory里面有BDMap属性、用来存储Bean名称以及BD
找到重写的方法 —>>>
//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//---------------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
中间代码省略、只粘贴重要的代码
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
将BD和BDName添加到BDMap中、然后删除已经添加过的.这样一来Spring将自己内部的类就添加到了DBMap中。
然后在继续分析第二行代码
this.scanner = new ClassPathBeanDefinitionScanner(this);
其实这里只是用来给外部进行调用、当我们需要多次扫描包或者类的时候可以将扫描出来的类转换为BD、Spring提供了这么一个方法提供我们调用。也就是说当我们外部调用applicationContext.scan(包名);方法时
、这里定义的ClassPathBeanDefinitionScanner对象才有意义。
最后总结:只是Spring把他内部的类转换成BD 存储到了BeanFactory中的DBMap当中、只是做了这个事情。
下面我们在来看我们自己传的类Spring是如何进行BD转换和存储到BDMap当中的。
applicationContext.register(Test.class);
跳转到以下方法 —>>
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
重点来看这一行代码 this.reader.register(annotatedClasses);
继续跳进下一个方法
/**
* Register one or more annotated classes to be processed.
*/
//注册一个类或者多个类
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
registerBean(annotatedClass);
继续跳进下一个方法
/**
* Register a bean from the given bean class, deriving its metadata from
*/
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
需要注意的是 以上的参数传递只传递了我们的类、其余的三个参数为空
重点的方法来了 看图
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//将外部带注解的类传进来、通过BD的实现类的构造方法、将类进行BD的转换
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//查看外部类是否是单例还是原型
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//存储在DBMap中的BDName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//判断外部类是否加了Lazy注解、DependsOn注解 等等
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//qualifiers永远等于空、因为是内部自己调用、自己传递参数 参考148行
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//创建一个存储BDName和BD的一个数据结构、后面会进行拆分
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
这里需要对某些代码进行一个详细的解析 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
前面说过 RootBeanDefinition是BeanDefinition的实现类可以通过构造方法将类进行BD的转换、那么这里Spring用的是AnnotatedGenericBeanDefinition对象、也可以将该类的构造方法将类进行一个BD的转换、只是Spring把他们之间分的很清楚什么类需要用什么对象
那么这里看到将带了注解的类转换成BD、只是BeanDefinition的实现类中定义的属性不同。
然后在看这个方法AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
absBd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
absBd.setDescription(description.getString("value"));
}
}
}
这一块代码其实很简单、就是看我们传进来的类是否加了这些注解、如果加了注解就往该BD中进行一个属性的填充。回到跳进上图方法之前的方法。
然后在看这一行代码BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
用来充当多参数整合到一起的参数、后面会有操作。
主要来看这一行代码BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
把上面定义的BDH(BeanDefinitionHolder)和注册器(BeanDefinitionRegistry)传入到了该方法当中、可以得出这个位置是要对我们的转换的BD进行一个注册。跳进这个方法
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
//将BeanDefinitionHolder对象进行拆分
//取出BDH中的BD 然后取出BDH中的BDName 一并传入该方法进行注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
最后还是将上面封装的BeanDefinitionHolder进行拆分、然后传到注册方法进行注册
最后总结:将我们的类通过BeanDefinition的实现类 AnnotatedGenericBeanDefinition 对象的构造方法将该类转换成BD、然后存储到BDMap中
。
applicationContext.refresh();
在解析该方法之前需要阐述两个类Spring中BeanFactoryPostProcessor和BeanPostProcessor都是Spring初始化bean时对外暴露的扩展点。两个接口从名字看起来很相似,但是作用及使用场景却不同。
跳进方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// 这里得到Bean工厂
// 该对象继承ConfigurableBeanFactory
// 而这个对象继承HierarchicalBeanFactory
// 而这个对象继承BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//准备Bean工厂、开始对Bean工厂进行属性填充
prepareBeanFactory(beanFactory);
try {
// 当前方法可能是Spring后续进行扩展的方法(里面什么代码都没有)
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//调用Bean工厂的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
.......................先展示一部分代码.......................
我们直接来解析这行关键代码invokeBeanFactoryPostProcessors(beanFactory); 以上的几个方法只是得到Bean工厂和Spring对工厂进行一些属性的填充。
下面跳到关键方法中去
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 首先说一下getBeanFactoryPostProcessors()这个方法的作用、这里Spring会去获取我们自定义的Bean工厂后置处理器
// 什么叫我们自定义的Bean工厂后置处理器(外部调用该方法 -->> applicationContext.addBeanFactoryPostProcessor(new 类名());
// 传入的类是实现了BeanFactoryPostProcessors接口)
// 然后进入调用方法
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
// Spring内部做的一些事情
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
这里说一下、如果我们不在外部调用applicationContext.addBeanFactoryPostProcessor(new 类名());那么这里getBeanFactoryPostProcessors();只会获得一个对象、那就是ConfigurationClassPostProcessor对象
继续进入调用方法
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//这里会进判断、因为BeanFactory内部有一个BeanDefinitionRegistry
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 存放我们自定义的类(实现了BeanFactoryPostProcessor接口的类)
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 存放我们自定义的类(实现了BeanDefinitionRegistryPostProcessor接口的类)
// -------------->>>>>>>>>> 【重点】 <<<<<<<<<<--------------
// 由于 BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor(子类多一个扩展方法)
// 但是你在外部调用applicationContext.addBeanFactoryPostProcessor(new 类名());时
// 你的类可能是实现了BeanFactoryPostProcessor接口的类、也有可能是实现了BeanDefinitionRegistryPostProcessor接口的类
// 所以Spring定义2个List进行一个区分
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//这里遍历我们自定义的Bean工厂的后置处理器、我们可以实现多个BeanFactoryPostProcessors接口
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//判断自定义的类是否是实现了BeanDefinitionRegistryPostProcessor接口的类
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
//实现了BeanFactoryPostProcessor接口的类
regularPostProcessors.add(postProcessor);
}
}
// 这里再次定义了一个BeanDefinitionRegistryPostProcessor类型的List、将Spring内部的类存放到该List中
// 这里得到的类是 ---->>>> ConfigurationClassPostProcessor 该类实现了BeanDefinitionRegistryPostProcessor接口
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 根据类型得到Bean名称(当BDMap中存放一个BD时、其实Spring会存储一个该类的类型、就是说每个类都有一个类型)
// 比如Test类在转换为BD时、Test的类型实际上是Dao类型、那么Test类变为BD时该BD的类的类型为Dao类型
// 该数组得到的结果:如果自定义的类实现了 BeanDefinitionRegistryPostProcessor接口 那么这里会得到自定义的类的名称
// 如果没有 那么这里只会得到Spring内部实现了BeanDefinitionRegistryPostProcessor接口的类的名称
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//将实现了BeanDefinitionRegistryPostProcessor的类 存放List中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//排序的后置处理器
sortPostProcessors(currentRegistryProcessors, beanFactory);
//将2个BeanDefinitionRegistryPostProcessor类型的List进行合并
registryProcessors.addAll(currentRegistryProcessors);
//调用BD注册器的后置处理器
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
大概的一个操作流程写在代码里面了、下面我们来看invokeBeanDefinitionRegistryPostProcessors();方法
/**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
// 如果这里传进来的BeanDefinitionRegistryPostProcessor类型的List中 没有自定义的类
// 那么该类只有ConfigurationClassPostProcessor一个类
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
//调用BeanDefinitionRegistryPostProcessor接口的扩展方法
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
需要说一下的是、postProcessor.postProcessBeanDefinitionRegistry(registry);调用的扩展方法是每个实现类的扩展方法;比如:public class Test implements BeanDefinitionRegistryPostProcessor 那么这里会进你实现的方法进行操作。我们这里只解析Spring内部实现了BeanDefinitionRegistryPostProcessor的方法 ------->>>> ConfigurationClassPostProcessor对象 该对象实现了这个对象
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//做一个Hash码的校验
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
//方法调用
processConfigBeanDefinitions(registry);
}
继续跳进 processConfigBeanDefinitions(registry);
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//得到DBMap中 所有的 BD名称
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
//遍历名称得到BD
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 判断该BD的配置信息
// 全配置类(configuration注解)、
// 部分配置类(Component注解、ComponentScan注解、Import注解、ImportResource注解(不包含configuration注解))
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// 校验当前BD是否是配置类、如果不是直接返回false、true进入条件
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
.......................先展示一部分代码.......................
我们先来看一下校验的代码checkConfigurationClassCandidate
/**
* Check whether the given bean definition is a candidate for a configuration class
*/
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
// 这里是我们加了@Configuration的全配置类
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// 得到配置类的所有注解
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// Check already loaded Class if present...
// since we possibly can't even load the class file for this Class.
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
metadata = new StandardAnnotationMetadata(beanClass, true);
}
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
}
return false;
}
}
// 如果是加了@Configuration注解
if (isFullConfigurationCandidate(metadata)) {
// 将该BD的属性里面添加一个full标记
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
//如果加了Configuration注解 这个if将不会进
else if (isLiteConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
该校验方法就是判断是否加了@Configuration注解、如果加了就为该BD添加一个FULL标记
然后继续回到上面没有显示完的代码(下半部分)
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 开始解析@ConfigurationBD
parser.parse(candidates);
parser.validate();
.......................先展示一部分代码.......................
主要看这段代码parser.parse(candidates); 解析加了@Configuration的BD
,跳进parser.parse方法
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<>();
for (BeanDefinitionHolder holder : configCandidates) {
// 获取BD
BeanDefinition bd = holder.getBeanDefinition();
try {
//我们BD是由AnnotatedBeanDefinition的构造方法进行的转换、这里是等于的
if (bd instanceof AnnotatedBeanDefinition) {
// 解析类
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
.......................先展示一部分代码.......................
这里说一下,由于我们的类是由AnnotatedBeanDefinition
构造出来的BD,所以会进入第一个判断语句,继续跳进看parse方法
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
// Explicit bean definition found, probably replacing an import.
// Let's remove the old one and go with the new one.
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// Recursively process the configuration class and its superclass hierarchy.
// ASM技术
SourceClass sourceClass = asSourceClass(configClass);
do {
// 扫描@ComponentScan的注解
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
// 这里会将扫描出来的类(加了@Compoent的类)和实现了ImportSelector接口、但是实现方法内返回的类是普通类
// 都会放进该Map中、然后进行注册(被扫描出来的会被Spring过滤掉、因为在扫描时已经把加了@Compoent的类进行了注册)
this.configurationClasses.put(configClass, configClass);
}
SourceClass sourceClass = asSourceClass(configClass);)该方法只是将我们的注册类用ASM转换成SourceClass对象。
我们主要解析的代码从doProcessConfigurationClass方法开始看起
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first
// 这里处理配置类里面的内部类、一般没有内部内
processMemberClasses(configClass, sourceClass);
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 处理加了@ComponentScan的注解
Set<AnnotationAttributes> 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
// 调用parse方法 执行扫描、
// 也就是说Spring是在这个方法里面直接将扫描出来的类转换成BD 直接注册到DBMap中
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
.......................先展示一部分代码.......................
这一段代码就是Spring正真的去扫描我们加了@Component注解的类 ----->>>>> this.componentScanParser.parse方法
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
//Spring内部定义的扫描,这里要说的一下
// ------------------------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 【由于最开始看源码的时候我们会知道,Spring在创建Spring环境的时候,
// 创建了一个(this.scanner = new ClassPathBeanDefinitionScanner(this);),但是Spring又在这里自己创建了一个这样的对象
// 其实在一开始创建出来的 this.scanner = new ClassPathBeanDefinitionScanner(this);对象是针对外部调用的,
// 这里创建的 ClassPathBeanDefinitionScanner 才是Spring正真的进行我们类的一个扫描】
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<------------------------------
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
// 由于在该位置BD还没有产生出来,所以Spring先将所有加了@Compoent的类,并且还加了@Lazy注解的,
// 在这里一并设置成统一的Lazy开关,等将BD创建出来后,在将@Lazy注解的值进行填充
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
Set<String> basePackages = new LinkedHashSet<>();
//得到@ComponentScan里面的值
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
该方法内主要是Spring对于我们的类加了@Lazy注解的进行处理,代码上写有注释,其中有一段代码这里要在解释一下,Spring在该方法中创建了一个ClassPathBeanDefinitionScanner对象,至于为什么会在这里创建对象,我在代码的注释中进行了解释。
最后我们看到scanner.doScan方法
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 将扫描出来的类进行BD转换 --->>>> findCandidateComponents方法内部进行的转换
// 最终findCandidateComponents方法内部进行转换的BD 是ScannedGenericBeanDefinition(定义为扫描出来的普通BD)
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 这里会进判断、因为执行findCandidateComponents方法时
// 内部将类通过 ScannedGenericBeanDefinition对象的构造将类进行BD转换
// 该对象继承了GenericBeanDefinition、而他又继承了AbstractBeanDefinition
if (candidate instanceof AbstractBeanDefinition) {
// 该方法是将BD设置的属性进行填充 Spring首先会将一套默认的属性进行填充、然后在将自定义的属性替换掉默认的属性
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//依然会进该判断、我们的BD是由AnnotatedBeanDefinition对象进行的转换
if (candidate instanceof AnnotatedBeanDefinition) {
// 该方法将我们的BD(AnnotatedBeanDefinition)属性进行填充
// (例如:是否加过Lazy注解、是否加过DependsOn注解、是否加过Description注解 等)
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 最终将扫描出来的类转换成BD后、直接就注册到BDMap中
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
看到这里就是Spring对我们加了@Component的类扫描出来后,转换成BD 然后直接进行注册。代码上的注释也有写,到这里Spring就完成了我类的扫描并且进行注册
前面Spring的扫描我们分析完了,我们继续分析加了import注解的类
,展示上面的doProcessConfigurationClass方法 没显示完代码
// 此处开始判断传入方法的类 是属于哪种@Import注解
// (@ImportSelector、@ImportBeanDefinitionRegistrar、还是普通类(只是被加了@import的类、但是都没有去实现前面2个接口))
// 这里的getImports()方法 是获取@import里面的值(也就是类)、返回出来的是一个Set<SourceClass>对象
processImports(configClass, sourceClass, getImports(sourceClass), true);
重点来分析这里段代码,processImports方法,getImports方法是干什么的文中的注释有写
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
//没有加@Import的类就直接返回了
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
//判断被引用的类是属于哪种Import(是实现ImportSelector接口的)
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
// 通过反射实现一个对象、因为Spring要知道、
// 实现了ImportSelector接口的实现方法内返回的是哪些字符串、
// 他需要得到一个类的类名、才能实现一个对象、进行DB的转换和BD注册
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
//得到实现方法内的类名
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//然后通过类名创建一个类、得到的类就是实现方法返回出来的类
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
// 如果是实现ImportSelector接口的、他会得到实现方法里面返回的类
// 在次调用本方法 在次去看该类是属于哪种Import
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
//判断被引用的类是属于哪种Import(是实现ImportBeanDefinitionRegistrar接口的)
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// 还是只是普通的类(没有实现上面的两种接口)
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
ConfigurationClass configurationClass = candidate.asConfigClass(configClass);
// 如果是实现了ImportSelector接口的、但是实现方法内返回的类是没有实现了ImportSelector接口的
// 那么就将该类进行类解析
// 【---------------->>>>>>>>>> 注意 <<<<<<<<<<----------------】
// 这里普通的类(没有实现上面的两种接口)、和实现了ImportSelector接口、但是实现方法内返回的类是普通类
// 都会在此处被放进同一个Map中
processConfigurationClass(configurationClass);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
// 这里会将扫描出来的类(加了@Compoent的类)和实现了ImportSelector接口、但是实现方法内返回的类是普通类
// 都会放进该Map中、然后进行注册(被扫描出来的会被Spring过滤掉、因为在扫描时已经把加了@Compoent的类进行了注册)
this.configurationClasses.put(configClass, configClass);
Spring将我们的类放进了该Map中this.configurationClasses -->> 注意:这里放进Map中的依然是类,还并没将类转换成BD
然后我们回到ConfigurationClassPostProcessor类的 -->> processConfigBeanDefinitions方法 里面的loadBeanDefinitions方法
// 到此为止
// 实现了ImportSelector接口的方法里面返回的类
// 实现了ImportBeanDefinitionRegistrar接口的类
// 注册到BDMap中
this.reader.loadBeanDefinitions(configClasses);
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
// 循环调用方法
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
我们看循环调用的方法内做了什么事情
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()) {
// 此处将普通类(被@Import引用的类)
// 实现了ImportSelector接口的方法里面返回的类(如果是普通类)
// 在此处进行BDMap的注册
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
// 此处将注册实现了ImportBeanDefinitionRegistrar的进行注册
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
在这里Spring针对不同的实现类,做了不同的注册方式,但是最后还是将类转换成BD,依次继续注册
那么Spring到目前位置完成了如何扫描包,如何将各注解解析后放入Bean工厂 --->>>invokeBeanDefinitionRegistryPostProcessors也就完成了这一个方法的所有处理操作
-----Coming soon -----