你有一份来自春天的信—Spring5.x 源码分析 : 从容器启动开始
Posted 黑骑士的冒险
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你有一份来自春天的信—Spring5.x 源码分析 : 从容器启动开始相关的知识,希望对你有一定的参考价值。
来源:来电
https://my.oschina.net/u/3136594/blog/3123433
Spring 已经是十分成熟的一个框架,此篇为开天辟地的Spring源码分析首发。读源码本来就是一件十分枯燥,具有一定难度,技巧性的有重要意义的事。万事开头难,我会利用空余时间持续的跟进文章的连载。对于喜爱源码的小伙伴,能够提供一定的帮助。
下面准备发车,需要的小伙伴,请搭乘spring 5.1.8列车准备起飞。。。
1、从容器启动开始
最简单的启动spring的代码如下:
import com.ld.test.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(AppConfig.class);
acac.close();
}
}
AnnotationConfigApplicationContext
先来看一下AnnotationConfigApplicationContext类的UML图,留个印象。
点开AnnotationConfigApplicationContext(AppConfig.class);方法查看源码:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// 调用默认无参构造器,里面有一大堆初始化逻辑
// 开天辟地初始化两个类
// AnnotatedBeanDefinitionReader reader;
// ClassPathBeanDefinitionScanner scanner;
this();
// 把传入的Class进行注册,Class既可以有@Configuration注解,也可以没有@Configuration注解
//
// 有@Configuration
// map.put("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass","full")
// 没有有@Configuration
// map.put("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass","lite")
//
// 怎么注册? 委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册
// 传入Class 生成 BeanDefinition , 然后通过 注册到 BeanDefinitionRegistry
register(annotatedClasses);
// 刷新容器上下文
refresh();
}
该构造器允许我们传入一个或者多个class对象。class对象可以是被@Configuration标注的,也可以是一个普通的Java 类。有参构造器调用了无参构造器,点开源码:
public AnnotationConfigApplicationContext() {
// 隐式调用父类构造器,初始化beanFactory,具体实现类为DefaultListableBeanFactory
// super();
// 创建 AnnotatedBeanDefinitionReader,
// 创建时会向传入的 BeanDefinitionRegistry 中 注册 注解配置相关的 processors 的 BeanDefinition
this.reader = new AnnotatedBeanDefinitionReader(this);
// 通过后面的源码探究也可以发现,spring并不是使用这个scanner来扫描包获取Bean的
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
初始化子类时会先初始化父类,会默认调用父类无参构造器。AnnotationConfigApplicationContext继承了GenericApplicationContext,在GenericApplicationContext的无参构造器中,创建了BeanFactory的具体实现类DefaultListableBeanFactory。spring中的BeanFactory就是在这里被实例化的,并使用DefaultListableBeanFactory做的BeanFactory的默认实现。
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
DefaultListableBeanFactory
AnnotationConfigApplicationContext的构造器中还创建了两个对象:AnnotatedBeanDefinitionReader 和ClassPathBeanDefinitionScanner。
ClassPathBeanDefinitionScanner scanner
先说scanner的作用,通过查看源码可以发现,这个scanner只有在手动调用AnnotationConfigApplicationContext的一些方法的时候才会被使用(通过后面的源码探究也可以发现,spring并不是使用这个scanner来扫描包获取Bean的)。
2、AnnotatedBeanDefinitionReader
创建AnnotatedBeanDefinitionReader对象。spring在创建reader的时候把this当做了参数传给了构造器。也就是说,reader对象里面包含了一个this对象,也就是AnnotationConfigApplicationContext对象。
AnnotationConfigApplicationContext实现了BeanDefinitionRegistry接口。点开this.reader = new AnnotatedBeanDefinitionReader(this);源码:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
从传入的BeanDefinitionRegistry对象,就是AnnotationConfigApplicationContext对象中获取Environment(共用同一个Environment),然后又接着调用另一个构造器。点开源码:
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);
//在 BeanDefinitionRegistry 中注册 注解配置相关的 processors
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
在这个构造器中,执行了一个非常重要的方法:AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 顾名思义,spring通过这个方法注册了解析注解配置相关的处理器。点开源码:
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// AnnotationAwareOrderComparator是OrderComparator的子类,用来支持Spring的Ordered类、@Order注解和@Priority注解。
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// 设置依赖注入的候选处理器
// 可以看到只要不是ContextAnnotationAutowireCandidateResolver类型 直接升级为最强类型
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
// 代码省略。。。
}
注册的是一些spring内置的PostProcessor的BeanDefinition。
2.1 ConfigurationClassPostProcessor
ConfigurationClassPostProcessor是一个 BeanFactoryPostProcessor和BeanDefiDefinitionRegistryPostProcessor处理器,BeanDefinitionRegistryPostProcessor的处理方法能处理@Configuration等注解。
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()方法内部处理@Configuration,@Import,@ImportResource和类内部的@Bean。
ConfigurationClassPostProcessor继承了BeanDefinitionRegistryPostProcessor,
BeanDefinitionRegistryPostProcessor类继承了BeanFactoryPostProcessor。通过BeanDefinitionRegistryPostProcessor可以创建一个特别后置处理器来将BeanDefinition添加到BeanDefinitionRegistry中,它和BeanPostProcessor不同,BeanPostProcessor只是在Bean初始化的时候有个钩子让我们加入一些自定义操作。
而BeanDefinitionRegistryPostProcessor可以让我们在BeanDefinition中添加一些自定义操作。在Mybatis与Spring的整合中,就利用到了BeanDefinitionRegistryPostProcessor来对Mapper的BeanDefinition进行了后置的自定义处理。
2.2 AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor是用来处理@Autowired注解和@Value注解的。
2.3 RequiredAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor这是用来处理@Required注解。
2.4 CommonAnnotationBeanPostProcessor
提供对JSR-250规范注解的支持@javax.annotation.Resource、@javax.annotation.PostConstruct和@javax.annotation.PreDestroy等的支持。
2.5 EventListenerMethodProcessor
EventListenerMethodProcessor提供@PersistenceContext的支持。
EventListenerMethodProcessor提供@ EventListener 的支持。@ EventListener是在spring4.2之后出现的,可以在一个Bean的方法上使用@EventListener注解来自动注册一个ApplicationListener。
我们发现:内部定义的class都是带internal的。
该方法从传入的BeanDefinitionRegistry对象,也就是AnnotationConfigApplica
tionContext对象中获取到DefaultListableBeanFactory对象。
为获取的DefaultListableBeanFactory对象设置属性。
往DefaultListableBeanFactory对象中注册BeanDefinition,注册的是一些spri
ng内置的PostProcessor的BeanDefinition(关于BeanDefinition的介绍下期在讲)。注意,此时只是注册BeanDefinition,并没有实例化bean。默认情况下,执行完该方法后,spring容器中所注册的BeanDefinition为:
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
注册内置Processor至容器:
所谓的注册BeanDefinition,简单理解就是将BeanDefinition放到DefaultListableBeanFactory.registerBeanDefinition对象的beanDefinitionMap中。
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);
//第一次进来existingDefinition肯定为null
if (existingDefinition != null) {
// 代码省略。。。
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
到此为止: DefaultListableBeanFactory.beanDefinitionMap 只有默认的 spring beanDefinition。
====下面是大家熟悉的注册默认6大后置处理器====
ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
Jpa的PersistenceAnnotationProcessor(没导包就不会注册)
EventListenerMethodProcessor
DefaultEventListenerFactory
3、ClassPathBeanDefinitionScanner
public AnnotationConfigApplicationContext() {
/**
* 创建一个读取注解的Bean定义读取器
* 什么是bean定义?BeanDefinition
*
* 完成了spring内部BeanDefinition的注册(主要是后置处理器)
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
/**
* 创建BeanDefinition扫描器
* 可以用来扫描包或者类,继而转换为bd
*
* spring默认的扫描包不是这个scanner对象
* 而是自己new的一个ClassPathBeanDefinitionScanner
* spring在执行工程后置处理器ConfigurationClassPostProcessor时,去扫描包时会new一个ClassPathBeanDefinitionScanner
*
* 这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
*
*/
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
下一步
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// 这个肯定成功
if (useDefaultFilters) {
/**
* 注册spring扫描类过滤器
* 加了特定注解的类会被扫描到
* 带有@Component、@Repository、@Service、@Controller、@ManagedBean、@Named
*/
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
只关心最后一个构造函数的registerDefaultFilters();方法:
/**
* 注册过滤器
* 带有@Component、@Repository、@Service、@Controller、@ManagedBean、@Named
* 注解的类会被spring扫描到
*
* Register the default filter for {@link Component @Component}.
* <p>This will implicitly register all annotations that have the
* {@link Component @Component} meta-annotation including the
* {@link Repository @Repository}, {@link Service @Service}, and
* {@link Controller @Controller} stereotype annotations.
* <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
* JSR-330's {@link javax.inject.Named} annotations, if available.
*
*/
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
扫描过滤器includeFilters与excludeFilters,首先这里的includeFilters大家熟悉吗,还有个excludeFilters,先看一下属性:
private final List<TypeFilter> includeFilters = new LinkedList<>();
private final List<TypeFilter> excludeFilters = new LinkedList<>();
这里提前往includeFilters里面添加需要扫描的特定注解:
添加元注解@Component,需要注意的是@Repository、@Service、@Controller里面都标注了@Component。很好理解,扫描的时候用includeFilters 去过滤时,会找到并处理这4个注解的类。
下面两个注解@ManagedBean、@Named需要有对应的jar包,否则(也就是说把这个方法走完),includeFilters里面只会有一个元素。
4、总结
this.reader = new AnnotatedBeanDefinitionReader(this);完成了spring内部BeanDefinition的注册(主要是后置处理器):
beanDefinitionMap存放了所有的Defintion 以 key-value
List<String> beanDefinitionNames 存放了所有的beanDefintion名字this.scanner = new ClassPathBeanDefinitionScanner(this);
这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法,提供了includeFilters 和 excludeFilters 这里是一个扩展点。
到此开天辟地初始化两句代码就完成了他们的使命。
以上是关于你有一份来自春天的信—Spring5.x 源码分析 : 从容器启动开始的主要内容,如果未能解决你的问题,请参考以下文章