Spring源码-IOC加载过程(注解方式加载)
Posted AC_Jobim
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码-IOC加载过程(注解方式加载)相关的知识,希望对你有一定的参考价值。
Spring源码-IOC加载过程(注解方式加载)
- 一、源码分析的入口
- 二、this()调用构造函数
- 三、register(annotatedClasses)注册配置类为BeanDefinition
- 四、refresh()
- 4.1 prepareRefresh()
- 4.2 obtainFreshBeanFactory()
- 4.3 prepareBeanFactory(beanFactory)
- 4.4 postProcessBeanFactory(beanFactory)
- 4.5 invokeBeanFactoryPostProcessors(beanFactory)(重点)
- 4.6 registerBeanPostProcessors(beanFactory)
- 4.7 initMessageSource()
- 4.8 initApplicationEventMulticaster()
- 4.9 onRefresh()
- 4.10 registerListeners()
- 4.11 finishBeanFactoryInitialization(beanFactory)(重点)
- 4.12 finishRefresh()
一、源码分析的入口
使用环境:SpringBoot2.1.16.RELEASE
-
Spring容器初始化入口,使用
AnnotationConfigApplicationContext
加载beanpublic static void main(String[] args) // 加载spring上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); Car car = context.getBean("car",Car.class); System.out.println(car.getName());
MainConfig.class:
@Configuration //作为配置类,替代 xml 配置文件 @ComponentScan(basePackages = "com.zb.demo.spring") public class SpringConfig
-
AnnotationConfigApplicationContext的构造方法
//根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少 public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) //1、调用无参构造函数,会先调用父类GenericApplicationContext的构造函数,父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory //2、本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner //scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的 this(); //3、把传入的类进行注册,这里有两个情况, //传入传统的配置类 和 传入bean(虽然一般没有人会这么做) //看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配置类 //但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean register(annotatedClasses); //刷新 refresh();
构造方法说明:
-
这是一个有参的构造方法,可以接收多个配置类,不过一般情况下,只会传入一个配置类。
-
这个配置类有两种情况,
- 一种是传统意义上的带上@Configuration注解的配置类,
- 另一种是没有带上@Configuration,但是带有@Component,@Import,@ImportResouce,@Service,@ComponentScan等注解的配置类,在Spring内部把前者称为Full配置类,把后者称之为Lite配置类。在本源码分析中,有些地方也把Lite配置类称为普通Bean。
-
二、this()调用构造函数
调用AnnotationConfigApplicationContext类的无参构造方法
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry
//注解bean定义读取器,主要作用是用来读取被注解的了bean
private final AnnotatedBeanDefinitionReader reader;
//扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext()
//会隐式调用GenericApplicationContext父类的构造方法,初始化DefaultListableBeanFactory
//初始化一个Bean读取器
this.reader = new AnnotatedBeanDefinitionReader(this);
//初始化一个扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
this.scanner = new ClassPathBeanDefinitionScanner(this);
- 首先无参构造方法中就是对读取器
reader
和扫描器scanner
进行了实例化- reader的类型是
AnnotatedBeanDefinitionReader
,可以看出它是一个 “打了注解的Bean定义读取器”, - scanner的类型是
ClassPathBeanDefinitionScanner
,它仅仅是在外面手动调用.scan方法,或者调用参数为String的构造方法,传入需要扫描的包名才会用到,像这样方式传入的配置类是不会用到这个scanner对象的。
- reader的类型是
2.1 super()隐式调用父类的构造方法
-
其中会隐式调用父类GenericApplicationContext的构造方法:实例化工厂DefaultListableBeanFactory
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry private final DefaultListableBeanFactory beanFactory; @Nullable private ResourceLoader resourceLoader; private boolean customClassLoader = false; private final AtomicBoolean refreshed = new AtomicBoolean(); /** * Create a new GenericApplicationContext. */ public GenericApplicationContext() /** * 调用父类的构造函数,为ApplicationContext spring上下文对象初始beanFactory * 为啥是DefaultListableBeanFactory?我们去看BeanFactory接口的时候 * 发现DefaultListableBeanFactory是最底层的实现,功能是最全的 */ this.beanFactory = new DefaultListableBeanFactory();
问题: BeanFactory有很多, 为什么初始化的时候选择DefaultListableBeanFactory呢?
DefaultListableBeanFactory的关系图:
通过观察, 我们发现, DefaultListableBeanFactory实现了各种各样的BeanFactory接口, 同时还是先了BeanDefinitionRegistry接口。
也就是说, DefaultListableBeanFactory不仅仅有BeanFactory的能力, 同时还有BeanDefinitionRegistry的能力. 它的功能是最全的。所以,我们使用的是一个功能非常强大的类Bean工厂类
2.2 初始化AnnotatedBeanDefinitionReader
this.reader = new AnnotatedBeanDefinitionReader(this);
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
//把ApplicationContext对象赋值给AnnotatedBeanDefinitionReader
this.registry = registry;
//用户处理条件注解 @Conditional os.name
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))
//注册了实现Order接口的排序器
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
//设置@AutoWired的候选的解析器:ContextAnnotationAutowireCandidateResolver
// getLazyResolutionProxyIfNecessary方法,它也是唯一实现。
//如果字段上带有@Lazy注解,表示进行懒加载 Spring不会立即创建注入属性的实例,而是生成代理对象,来代替实例
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver))
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
/**
* 1.为我们容器中注册了解析我们配置类的后置处理器ConfigurationClassPostProcessor
* 名字叫:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
*/
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));
/**
* 2.为我们容器中注册了处理@Autowired 注解的处理器AutowiredAnnotationBeanPostProcessor
* 名字叫:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
*/
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));
/**
* 3.为我们容器注册处理JSR250规范的注解处理器CommonAnnotationBeanPostProcessor
* org.springframework.context.annotation.internalCommonAnnotationProcessor
*/
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));
/**
* 4.处理jpa注解的处理器org.springframework.orm.jpa.support.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));
/**
* 5.处理监听方法的注解@EventListener解析器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));
/**
* 6.注册事件监听器工厂
*/
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;
在这里注册了6个后置处理器的Bean定义:
2.3 初始化bean定义扫描ClassPathBeanDefinitionScanner
this.scanner = new ClassPathBeanDefinitionScanner(this);
- 创建BeanDefinition扫描器,可以用来扫描包或者类,进而转换为bd
- Spring默认的扫描包不是这个scanner对象,而是自己new的一个ClassPathBeanDefinitionScanner,Spring在执行后置处理器ConfigurationClassPostProcessor时, 去扫描包时会new一个ClassPathBeanDefinitionScanner
- 这里的scanner仅仅是为了程序员可以手动调用,AnnotationConfigApplicationContext对象的scan方法, 通过调用context.scan(“package name”);扫描处理配置类。
比如,可以这样使用:
public static void main(String[] args)
// 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStarter.class);
context.scan("package name");
Car car = (Car) context.getBean("car");
System.out.println(car.getName());
context.close();
三、register(annotatedClasses)注册配置类为BeanDefinition
register(annotatedClasses);
最终调用doRegisterBean(beanClass, null, null, null)方法将配置类注册成bean定义
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers)
//AnnotatedGenericBeanDefinition可以理解为一种数据结构,是用来描述Bean的,这里的作用就是把传入的标记了注解的类
//转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析
if (this.conditionEvaluator.shouldSkip(abd.getMetadata()))
return;
abd.setInstanceSupplier(instanceSupplier);
//解析bean的作用域,如果没有设置的话,默认为单例
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//获得beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解,这里没有判断注解的有效性),如果我们在外面,以类似这种
//AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);常规方式去初始化spring,
//qualifiers永远都是空的,包括上面的name和instanceSupplier都是同样的道理
//但是spring提供了其他方式去注册bean,就可能会传入了
if (qualifiers != null)
//可以传入qualifier数组,所以需要循环处理
for (Class<? extends Annotation> qualifier : qualifiers)
//Primary注解优先
if (Primary.class == qualifier)
abd.setPrimary(true);
//Lazy注解
else if (Lazy.class == qualifier)
abd.setLazyInit(true);
//其他,AnnotatedGenericBeanDefinition有个Map<String,AutowireCandidateQualifier>属性,直接push进去
else
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
for (BeanDefinitionCustomizer customizer : definitionCustomizers)
customizer.customize(abd);
//这个方法用处不大,就是把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,
//DefaultListableBeanFactory维护着一系列信息,比如beanDefinitionNames,beanDefinitionMap
//beanDefinitionNames是一个List<String>,用来保存beanName
//beanDefinitionMap是一个Map,用来保存beanName和beanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
在这里又要说明下,以常规方式去注册配置类,此方法中除了第一个参数,其他参数都是默认值。
- 通过AnnotatedGenericBeanDefinition的构造方法,获得配置类的BeanDefinition。
- 判断需不需要跳过注册,Spring中有一个@Condition注解,如果不满足条件,就会跳过这个类的注册。
- 然后是解析作用域,如果没有设置的话,默认为单例。
- 获得BeanName。
- 解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description。
- 限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解,这里没有判断注解的有效性)。
- 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中(这个不是很重要,可以简单的理解为方便传参)。
- 注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册
四、refresh()
refresh()
是 Spring 最核心的方法,没有之一,上帝就是用这个方法创造了 Spring 的世界。这是一个同步方法,用synchronized
关键字来实现的。该方法包含以下12个核心方法。用来加载活刷新Spring配置,使配置生效
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
//1.准备刷新上下文环境
prepareRefresh();
//2.获取告诉子类初始化Bean工厂不同工厂不同实现
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//还是一些准备工作,添加了两个后置处理器:ApplicationContextAwareProcessor,ApplicationListenerDetector
//还设置了忽略自动装配和允许自动装配 的接口,如果不存在某个bean的时候,spring就自动注册singleton bean
//还设置了bean表达式解析器等
prepareBeanFactory(beanFactory);
try
//4.留个子类去实现该接口
postProcessBeanFactory(beanFactory);
//5.调用我们的bean工厂的后置处理器. 1. 会在此将class扫描成beanDefinition 2.bean工厂的后置处理器调用
invokeBeanFactoryPostProcessors(beanFactory);
//6.注册我们bean的后置处理器
registerBeanPostProcessors(beanFactory);
//7.初始化国际化资源处理器.
initMessageSource();
//8.创建事件多播器
initApplicationEventMulticaster();
//9.这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomcat的.
onRefresh();
//10.把我们的事件监听器注册到多播器上
registerListeners();
//11.实例化我们剩余的单实例bean.
finishBeanFactoryInitialization(beanFactory);
//12.最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)
finishRefresh();
catch (BeansException ex)
if (logger.isWarnEnabled())
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
finally
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
4.1 prepareRefresh()
该方法用于容器刷新前的准备,包括设置上下文状态,获取属性,验证必要的属性等
// 设置启动时间
this.startupDate = System.currentTimeMillis();
// 1交给子类实现,初始化属性源
initPropertySources();
// 验证所有标记为必须的属性
getEnvironment().validateRequiredProperties();
4.2 obtainFreshBeanFactory()
该方法获取新的beanFactory。该方法很简单,刷新 BeanFactory 和获取 getBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory()
refreshBeanFactory();
return getBeanFactory();//返回我们的bean工厂,this()中new的工厂
4.3 prepareBeanFactory(beanFactory)
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.谈谈Spring的IoC之注解扫描