看了Spring源码也有一阶段了,但是博客一直没有总结,因为源码这个东西,总结起来是真的难,想让别人看懂的博客更难。我也看了很多csdn上的一些别的Spring源码的博客,总觉得很多东西都讲的一知半解,大多数把一个方法复制过来,说下这个方法大致干啥就没了,很多重要的细节可能自己都没搞明白呢。我总结了他们写的源码博客的经验,打算来一个代码全程Debug的方式,很多重要的代码一行行解析的方式来记录。这样做的好处就是,别人看不到我的代码可以自己调试,不会无厘头吧。这个方式不好的地方就是,你需要把我的博客从第一篇看,不然很难跟上我的节奏。希望大家能对Spring的源码有所了解,我也能多spring的源码有更多的收获吧。
进入正题:
这篇的博客,本着先大后小的原则,我会大概过一遍spring的BeanFactory初始化过程,主要是为了了绘制下spring的BeanFactory到底放了哪些东西,还有Spring的一些定义之类的概念相关的东西,过一个眼熟。这个图绘制完成,再看Spring的源码,你就不会那么晕了,很多东西你都能从这个图上找到对应的名字。在开始之前,我先简单的介绍几个知识点,可能是你看源码出现最多的几个单词吧(个人的理解)
1BeanDefinition: 以后都简称bd,所谓的bean定义,可以类比理解,我们知道java可以用Class描述一个class,描述这个class有哪些feild method等信息,spring也这样做的,它用bd来描述bean的属性,描述一个bean是否懒加载,作用域,名称.....
2.beanFactory:bean工厂,就是存放bd的地方,当然还有很多东西,就是spring环境的原料和机器
废话不多说,我们来搭建这个最简单的项目吧。
1.导入依赖(只需要导入spring-content即可)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
</dependencies>
2.创建一个配置类
@Configuration
@ComponentScan({"com.carry"})
public class Appconfig {
}
3.初始化spring的AnnotationConfigApplicationContext
public class SpringDemoApplicationContext {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(Appconfig.class);
applicationContext.refresh();
}
}
前期的准备工作就这么多,下面就要进入源码分析了,请做好,准备发车啦,准备好晕车药和红牛,干起来!!!
1.分析第一行代码:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
点进去看他的构造方法:
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
我们有点java基础的都应该知道,实例化之类构造方法之前,会调用父类的构造方法,所以,我们要看
AnnotationConfigApplicationContext的父类GenericApplicationContext的构造方法:
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
会创建一个我们这篇文章的主角,如果我们不点进去它的父类去看,你都不知道这个beanFactory在哪创建的
我们可以看下这个很神秘的bean工厂,里面有啥属性吧
/** Map from serialized id to factory instance */
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<>(8);
/** Optional id for this factory, for serialization purposes */
@Nullable
private String serializationId;
/** Whether to allow re-registration of a different definition with the same name */
private boolean allowBeanDefinitionOverriding = true;
/** Whether to allow eager class loading even for lazy-init beans */
private boolean allowEagerClassLoading = true;
/** Optional OrderComparator for dependency Lists and arrays */
@Nullable
private Comparator<Object> dependencyComparator;
/** Resolver to use for checking if a bean definition is an autowire candidate */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
/** Map from dependency type to corresponding autowired value */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** Map of singleton and non-singleton bean names, keyed by dependency type */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
/** Map of singleton-only bean names, keyed by dependency type */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
/** List of bean definition names, in registration order */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** List of names of manually registered singletons, in registration order */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
/** Cached array of bean definition names in case of frozen configuration */
@Nullable
private volatile String[] frozenBeanDefinitionNames;
/** Whether bean definition metadata may be cached for all beans */
private volatile boolean configurationFrozen;
只把这边几个重要的属性,画在图上去
回到AnnotationConfigApplicationContext这个类的构造方法
this.reader = new AnnotatedBeanDefinitionReader(this);
创建了一个bean的读取器,顾名思义,给我一个类,这个reader可以转换成bd
我们可以看下,我们从这个reder的构造器点进去发生了什么?
this.reader = new AnnotatedBeanDefinitionReader(this);
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
我们看下传一个this(AnnotationConfigApplicationContext对象)但是这边用BeanDefinitionRegistry去接收,说明了,这个BeanDefinitionRegistry和和AnnotationConfigApplicationContext是一样(因为AnnotationConfigApplicationContext的子类实现了BeanDefinitionRegistry这个接口哦)
看下构造方法:
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)) {
//AnnotationAwareOrderComparator主要能解析@Order注解和@Priority
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
//ContextAnnotationAutowireCandidateResolver提供处理延迟加载的功能
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//BeanDefinitio的注册,这里很重要,需要理解注册每个bean的类型
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//需要注意的是ConfigurationClassPostProcessor的类型是BeanDefinitionRegistryPostProcessor
//而 BeanDefinitionRegistryPostProcessor 最终实现BeanFactoryPostProcessor这个接口
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor
//MergedBeanDefinitionPostProcessor 最终实现了 BeanPostProcessor
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,设置它的setDependencyComparator和提供延迟加载的ContextAnnotationAutowireCandidateResolver,具体代码这一次就不分析了,我们第一篇博客的目的是,清楚Spring的BeanFactory到底有什么东西的。
后面的代码就是构建这个方法的返回值:BeanDefinitionHolder,我们可以看下它的数据结构,就是封装下beaName和bd
我们详细看下这段代码:
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
//BeanDefinitio的注册,这里很重要,需要理解注册每个bean的类型
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//需要注意的是ConfigurationClassPostProcessor的类型是BeanDefinitionRegistryPostProcessor
//而 BeanDefinitionRegistryPostProcessor 最终实现BeanFactoryPostProcessor这个接口
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
这段代码很重要哦:我们来一行行解读下:
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME))
我们这个registry或者是spring这个大环境下是否存在一个这个名字的bd(我们这个可是一个很干净的registry,肯定没有,肯定能进这个if里面)
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
这段代码也很经典:从这段代码,我们可以知道一个东西,spring自己内部的内,装换成bd的方式:即,new一个RootBeanDefinition,并把类实例传过去即可
def.setSource(source);
这个代码没有用的,因为这个source是我们传过来的,默认传的就是null
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
这个就是往bdh里面设置我们的bd,可以看下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);
}
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); 设置这个值为2,标识这个bd是人家spring自己的,和你没关系的
registry.registerBeanDefinition(beanName, definition);这行代码就是往我们的容器里面设置bd
return new BeanDefinitionHolder(definition, beanName); 返回bdh
这些代码执行完成之后,大家可以猜测下我们的registry里面有多少BeanDefinition了???
答案是:六个,具体的,可以自己debug看下,都是spring自己的bd
现在我们自己的bd图可以如下:
好了 this.reader = new AnnotatedBeanDefinitionReader(this);这行代码已经执行完成了,我们来看看我们从这行代码收获了什么:首先有了6个spring的bd,还知道了怎样从一个类转成bd的方式,也就是上图出现的元素,都是这行代码做的
下面来分析:this.scanner = new ClassPathBeanDefinitionScanner(this);
可以用来扫描包或者类,继而转换成bd,但是实际上,我们扫描包工作的scanner不是用的这个,是spring自己new的一个ClassPathBeanDefinitionScanner,这个我们后面后讲到的,大家不用着急,这里用其实也就是为了程序员你能在AnnotationConfigApplicationContext对象的scan方法
到此:
这里面的第一行代码执行完毕:我们应该有很大的收获吧,详情可以看图.
我们来分析applicationContext.register(Appconfig.class);第二行代码
我们可以一直点下去,里面都是方法的调用,真正干活的方法是doRegisterBean
/**
* Bean 定义读取器向容器注册注解 Bean 定义类
*/
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 根据指定的注解bean定义类,创建Spring容器中对注解Bean的封装的数据结构
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//解析注解 Bean 定义的作用域,若@Scope("prototype"),则 Bean 为原型类型;
//若@Scope("singleton"),则 Bean 为单利类型
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 为注解bean定义生成Bean名称
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 处理注解bean定义中的通用注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//如果在向容器注册注解 Bean 定义时,使用了额外的限定符注解,则解析限定符注解。
//主要是配置的关于 autowiring 自动依赖注入装配的限定条件,即@Qualifier 注解
//Spring 自动依赖注入装配默认是按类型装配,如果使用@Qualifier 则按名称
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
//如果配置了@Primary 注解,设置该 Bean 为 autowiring 自动依赖注入装//配时的首选
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
//如果使用了除@Primary 和@Lazy 以外的其他注解,则为该 Bean 添加一
//个 autowiring 自动依赖注入装配限定符,该 Bean 在进 autowiring
//自动依赖注入装配时,根据名称装配限定符指定的 Bean
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//创建一个指定Bean名称的bean定义对象,封装注解Bean定义数据
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 根据注解Bean定义类中配置的作用域,创建相应的代理对象
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 像ioc容器注册注解bean类定义对象
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
这里面的代码基本都有注释,我选几个重要的来讲一下(后面会全面的讲的,里面的很多方法,我都会一行一行带大家看的,还是那句话,看源码,先大后小,这篇博客的目的就是介绍spring的BeanFactory和一些常见的通用名称):
第一行代码就很重要,
// 根据指定的注解bean定义类,创建Spring容器中对注解Bean的封装的数据结构
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
我们上面从reader里面,知道,spring内部的对象转成bd是用RootBeanDefinition来new,
那么这行代码,告诉我们,加了注解的类可以通过new AnnotatedGenericBeanDefinition(annotatedClass);来创建
再看下最后一行的代码:
// 像ioc容器注册注解bean类定义对象
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
/**
* 将解析的 BeanDefinitionHold 注册到容器
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
// 获取解析的BeanDefinition的名称
String beanName = definitionHolder.getBeanName();
//像ioc容器中注册BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
// 如果BeanDefinition有别名。像容器注册其别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
这个就是用register注册我们的bd
这段代码执行完毕之后,我们BeanFactory里面就有7个bd了,六个spring自定义的(其中一个ConfigurationClassPostProcessor
很重要),还有一个就是我们的AppConfig,明白否?
我们打个refresh之前打个断点看下,执行完,前两行代码,我们的spring大环境都有神马东西,我们的BeanFactory有什么东西
再看看我们做的图都有哪些属性:
好了,至此,前两行代码执行的成果已经完成了。希望大家能坚持下去,我肯定会尽力写好这些spring的细节的(循环依赖,bean的生命周期,后置处理器等原理我都会分析的),希望大家能多多支持。