内容来自【自学星球】
欢迎大家来了解我的星球,和星主(也就是我)一起学习 Java ,深入 Java 体系中的所有技术。我给自己定的时间是一年,无论结果如何,必定能给星球中的各位带来点东西。
想要了解更多,欢迎访问:自学星球
该文章的内容有视频讲解,地址:点我直达
Spring 容器启动据我所了解的有三种
对于第一种和第三种都不是本次我所要分析的切入口,因为现在 Spring 开发都是盛行注解试开发,所以第二种方式的分析更符合我们学习的目标。
但是,不是说我只分析第二种,你们就不看其他方式了,我不分析是因为我也知道其他两种的启动流程,而你们却不清楚,所以你们要在闲暇之余看看其他两种的启动流程(学东西不要只学一部分
)。
好了,说清楚这点,那我们就开始往下分析吧!
切入口
public class ContextMain {
public static void main(String[] args) {
// 读取配置文件启动
AnnotationConfigApplicationContext annotationApplicationContext =
new AnnotationConfigApplicationContext(StudySpringConfiguration.class);
}
}
new Spring 注解应用山下文类通过传入注解配置类启动 Spring 。
进入该类构造器方法
org.springframework.context.annotation.AnnotationConfigApplicationContext # AnnotationConfigApplicationContext
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// 1、创建BeanFactory、向 BeanFactory 中添加各种注解解析器和 Bean 扫描规则
this();
// 2、向 BeanFacitry 中注册主配置类
register(annotatedClasses);
// 3、执行应用上下文刷新方法
refresh();
}
根据我上面代码注释,大家很清楚这三行的总体作用了,那我们下面每一行代码再具体分析分析。
首先是 this() 方法,通过调用当前空参构造器来到下面代码:
org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext()
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);
}
看到这里,我们先不着急点进代码,好好想想,子类构造器默认第一行会执行谁的构造器?
对,就是父类构造器,所以这里,我们应该网上找到它的父类,去看看它父类空参构造器干了些啥。
org.springframework.context.support.GenericApplicationContext#GenericApplicationContext()
public GenericApplicationContext() {
// 创建默认 BeanFactory
this.beanFactory = new DefaultListableBeanFactory();
}
还记得我们上面提到的核心类嘛,其中就有这个 BeanFactory 。原来,在 Spring 启动的时候,其默认的 BeanFactory 是这么创建出来的。
好,接着往下分析。
前面提到,该代码的作用是向容器中添加各种处理器,那具体是哪些处理器,又是怎么添加的是我们所要关心的点。
那,我们具体来分析分析。
入口代码
this.reader = new AnnotatedBeanDefinitionReader(this);
进入
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader
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);
/**
* registerAnnotationConfigProcessors
* 根据名字顾名思义就是->注册注解配置的的处理器
* 也就是这个方法里面会注册一些用于处理注解的处理器
*/
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
在进入
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 获取beanFactory也就是DefaultListableBeanFactory
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<>(4);
/**
* spring默认的BeanDefinition的注册,很重要,需要理解每个bean的类型
*/
// 注册ConfigurationAnnotationProcessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册AutowiredAnnotationBeanPostProcessor
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));
}
// 注册RequiredAnnotationBeanPostProcessor
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.
// 注册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.
// 注册PersistenceAnnotationProcessor
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));
}
// 注册EventListenerMethodProcessor
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));
}
// 注册DefaultEventListenerFactory
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;
}
这段代码就做了两件事情:
七种默认 Bean
PersistenceAnnotationBeanPostProcessor
这个类,很明显这是对jpa
的处理,所以需要引入spring-orm的包,没有引入的话则spring不会注册这个类@EventListener
注解的处理,spring实现事件监听的方式有很多种,其中一种就是在方法上添加@EventListener
注解那么注册这七种默认 Bean 的方法如下:
org.springframework.context.annotation.AnnotationConfigUtils#registerPostProcessor
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
/**
* registry就是AnnotationApplicationContext
* 这里是调用父类GenericApplicationContext中的registerBeanDefinition方法
* 调用beanFactory将spring默认的BeanDefinition注册进去
*/
registry.registerBeanDefinition(beanName, definition);
// 返回一个 BeanDefinitionHolder,就是 beanName 与 BeanDefinition 的合体
return new BeanDefinitionHolder(definition, beanName);
}
在进入
org.springframework.context.support.GenericApplicationContext#registerBeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// 一开始就初始化了DefaultListableBeanFactory
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
最后会来到真正注册的方法
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
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");
// AbstractBeanDefinition是实现了BeanDefinition接口的一个抽象类,是一个BeanDefinition的一个基础抽象类
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
/**
* 注册前的最后一次校检,这里的校检不不同于之前的XML文件校检。
* 主要是对AbstractBeanDefinition属性的methodOverrides校检
* 校检methodOverrides是否与工厂方法并存或者methodOverrides对应的方法根本不存在
*/
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
//在注册bd的时候判断该名字有没有被注册
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
//该名字已经被注册
//spring 默认支持覆盖bd,但是spring会输出一些日志
//1.两个bd相同的情况下
//2.两个bd不相同的情况 role不同
//3.两个bd不相同但是role相同
if (!isAllowBeanDefinitionOverriding()) {
// 如果对应的BeanName已经注册且配置中不允许覆盖,则抛出异常
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
// 向 Map 中添加 beanDefinition 完成注册
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// Spring容器是否开启实例化bean了
// 判断 alreadyCreated(Set集合) 属性值是否为空,空则为开始实例化
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
// 同步,安全,原子的向 beanDefinitionMap 中注册 beanDefinition
synchronized (this.beanDefinitionMap) {
// 向 Map 中添加 beanDefinition 完成注册
this.beanDefinitionMap.put(beanName, beanDefinition);
// 生成对应大小的手动注册单例的名称列表
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
// 添加Bean名称
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
// 替换
this.beanDefinitionNames = updatedDefinitions;
//如果你注册了beandefinition的名字和手工注册的bd集合当中某个相同则删除手工注册的beanName
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
// 与上面功能相同
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 判断注册的bd是否存在,根据 beanName
if (oldBeanDefinition != null || containsSingleton(beanName)) {
// 清除 allBeanNamesByType,把单例池当中的bean也remove
resetBeanDefinition(beanName);
}
}
这个方法有非常多的功能,但是主体还是围绕 Bean 的注册,所以总结出来的主要功能为:
好了,至此向容器中添加默认的 Bean(后置处理器) 流程分析完毕!
我有话说
:1、DefaultListableBeanFactory 中除了有两个 Map(beanDefinitionMap、beanDefinitionNames) 以外,还有一个 manualSingletonNames ,他存放什么场景的 BeanName ,它的元素又是怎么添加进去的
答:
Spring 中将 Bean 放入单例缓存池有两种方式,这两种方式能分别放进 beanDefinitionmap 和manualSingletonNames 集合中。
第一种(自动注入):
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeConfiguration.class); // 注册 Bean 的形式 applicationContext.register(People.class);
放入 beanDefinitionmap 中
第二种(手工注入):
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeConfiguration.class); // 直接放到单例池中 applicationContext.getBeanFactory().registerSingleton("people", new People());
放入 manualSingletonNames 中
2、在 Spring 而言,单例池中的 Bean 名称不能相同,如果自动注入和手工注入的 Bean 名称一样那么会移除手工注入中 manualSingletonNames 集合中的元素
3、自动注入有完整的 Bean 生命周期流程,而手工却没有
那,最后画图能手对于本小结画个流程图,进行收尾
下面我们来到创建BeanDefinition扫描器的代码,切入口
this.scanner = new ClassPathBeanDefinitionScanner(this);
通过一步步进入,最终来到下面方法
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// 默认 true
if (useDefaultFilters) {
/**
* 注册spring扫描类过滤器
* 加了特定注解的类会被扫描到
* 带有@Component、@Repository、@Service、@Controller、@ManagedBean、@Named
*/
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
很显然我们的关注点主要在 registerDefaultFilters 方法
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#registerDefaultFilters
protected void registerDefaultFilters() {
// 向 includeFilters 属性添加过滤规则 @Component
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
// 向 includeFilters 属性添加过滤规则 @ManagedBean
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.debug("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 {
// 向 includeFilters 属性添加过滤规则 @Named
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
该方法主要是向 includeFilters 属性赋值,其中主要添加了三种过滤规则:
暂时我的关注点只会在第一种 @Component ,因为这是我在 Spring 中经常用的,那有一点很奇怪,@Controller、@Service、@Repository 等注解我们却没看到有规则加入,why?
其实@Controller、@Service、@Repository等这些是一个复合注解,其内部包含了 @Component 注解,所以 Spring 底层只需要加入 @Component 这一个扫描规则其他复合注解就能生效。
最后也画一下 this 方法的整体流程图
切入口
org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext
register(annotatedClasses)
点击进入,最终回来到下面方法
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 封装主配置类为 BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
// 判断是否需要跳过
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// 给 BeanDefinition 设置相关属性
abd.setInstanceSupplier(instanceSupplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 给 BeanDefinition 设置懒加载、优先级、Qualifier自动注入
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
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));
}
}
}
// definitionCustomizers 默认为空,所以这个循环不会进
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
// 根据名字和 BeanDefinition 封装成 BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 判断是否需要代理
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 真正去注册 BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
我们来总结一下这个方法大致步骤:
注
:Bean 定义就是 BeanDefinition
至于这个注册方法 registerBeanDefinition
在上面的笔记中我已经分析了【10.3 小结】。
好了,今天的内容到这里就结束了,我是 【J3】关注我,我们下期见
。
由于博主才疏学浅,难免会有纰漏,假如你发现了错误或偏见的地方,还望留言给我指出来,我会对其加以修正。
如果你觉得文章还不错,你的转发、分享、点赞、留言就是对我最大的鼓励。
感谢您的阅读,十分欢迎并感谢您的关注。