因为我还是比较喜欢转载的,人家总结的漂漂亮亮的,何苦自己在整轮子,但是关于spring容器初始化过程相关文章,是在找不到一个合适的,所以自己整理了一篇。
废话不多说,直接上代码,因为后面废话更多,如有错误,留言指正,都是学习
首先准备一个测试代码:
public class IocTest2 {
public static void main(String[] args) {
BeanFactory context = new AnnotationConfigApplicationContext(IcoAppConfig2.class);
Bean1 bean = context.getBean(Bean1.class);
bean.say();
}
}
public class Bean1 {
public void say(){
System.out.println("say");
}
}
@Configuration
public class IcoAppConfig2 {
@Bean
public Bean1 bean1(){
return new Bean1();
}
}
下面开始根据断点,一步一步记录一下,咱们Spring容器做了啥
1. AnnotationConfigApplicationContext
先看一下AnnotationConfigApplicationContext的继承关系
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 由于他有父类,故而先调用父类的构造方法。然后调用自己的构造方法
this();
register(componentClasses);
refresh();
}
1. 先调用当前类的构造方法
因为当前类的父类有构造方法,所以先调用父类的构造方法
- 先在DefaultResourceLoader中初始化一个ClassLoader
- 在AbstractApplicationContext 初始化一个ResourcePatternResolver
- 在GenericApplicationContext中初始化一个DefaultListableBeanFactory✨
- 进入AnnotationConfigApplicationContext的构造函数中
/**
* 初始化一个bean的读取和扫描器,容器不包含任何 Bean 信息,如果直接调用构造方法,需要调用器register()去注册配置类,
* 并调用refresh() 方法刷新容器,触发容器对注解bean的载入、解析和注册过程
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
/*
* 父类的构造方法
* 创建一个读取被注解的Bean定义读取器
* 什么是bean定义?BeanDefinition
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
/*
* 可以用来扫描包或者类,继而转换成BeanDefinition,但是实际上我们扫描包工作不是scanner这个对象来完成的,
* 而是spring自己new的一个ClassPathBeanDefinitionScanner,
* 具体是在ComponentScanAnnotationParser.parse这个方法中new的scanner
* 这里的scanner仅仅是为了程序员能在外部调用AnnotationConfigApplicationContext对象的scan方法。
* */
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
先说说初始化的reader做了哪些事情:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
- conditionEvaluator 是一个内部类,用于evaluate Conditional 注解的,这里面会初始化ConditionContextImpl对象
- AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);这个方法,做了很多事情,我们看一下源码
/**
* 该方法主要是向容器注册了一组基础设施PostProcessor bean定义,
* 这些bean定义生成的PostProcessor实例被框架自己用于识别注解配置类中的bean定义。
* 它们里面还有一些作用于BeanDefinitionRegistry(容器级)的BeanDefinitionRegistryPostProcessor,
* 和作用于BeanFactory(容器级)的BeanFactoryPostProcessor,其它才是一般bean级别的BeanPostProcessor。
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// registry是GenericApplicationContext类型的,就返回他的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<>(8);
// BeanDefinition的注册,这里很重要,需要理解注册每个bean的类型 知识点:beanPostProcessor和beanFactoryPostProcessor
// why?因为需要在invokeBeanFactoryPostProcessors
// invokeBeanFactoryPostProcessors主要是在spring的beanFactory初始化的过程中去做一些事情,怎么来做这些事情呢?
// 委托了多个实现了BeanDefinitionRegistryPostProcessor或者BeanFactoryProcessor接口的类来做这些事情,有自定义的也有spring内部的
// 其中ConfigurationClassPostProcessor就是一个spring内部的BeanDefinitionRegistryPostProcessor。
// 因为如果你不添加这里就没有办法委托ConfigurationClassPostProcessor做一些功能
// 到底哪些功能?参考下面的注释
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最终实现BeanFactoryPostProcessor这个接口
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_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.beanDefinitionNames这个map中添加五个PostProcessor,这个很重要
beanDefinitionNames
0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
3 = "org.springframework.context.event.internalEventListenerProcessor"
4 = "org.springframework.context.event.internalEventListenerFactory"
再说说初始化的scanner做了哪些事情:
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
// 为容器设置加载Bean定义的注册器
this.registry = registry;
if (useDefaultFilters) {
/* 注册@Component的默认过滤器。这将隐式注册所有具有@Component元注释的注解,
* 包括@Repositor、@Service@Controller构造型注解。
* 同时还支持javax.annotation.ManagedBean,javax.inject.Named这两个注解
*/
registerDefaultFilters();
}
setEnvironment(environment);
// 为容器设置资源加载器
setResourceLoader(resourceLoader);
}
所以说, 他并没有实质上做什么事情, 也没有去scan,也没有去实例化
2. register(componentClasses)
这个componentClass,也就是我们从测试方法中传过来的IcoAppConfig2这个类。跟踪源码,我们找到主要的方法,其中只有第一个参数Class beanClass是有值的,其他都是null
/**
* Bean定义读取器向容器注册注解Bean定义类
* 下面的这句话就是说:根据Bean的注解获取元数据
* Register a bean from the given bean class, deriving its metadata from
* class-declared annotations.
* @param beanClass the class of the bean 根据类型byBeanType
* @param name an explicit name for the bean 根据名称 byBeanName 当前null
* @param supplier a callback for creating an instance of the bean 创建bean的实例的回调 当前null
* (may be {@code null})
* @param qualifiers specific qualifier annotations to consider, if any, 主要是@Qualifier注解 当前null
* in addition to qualifiers at the bean class level
* @param customizers one or more callbacks for customizing the factory's 当前null
* {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
* @since 5.0
*/
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构 就是这个BeanClass的表述
// AnnotatedGenericBeanDefinition 包含了类的其他信息,比如一些元数据,scope,lazy等等
// 跟踪源码发现,他实际上是初始化了beanClass,metadata
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
// 解析注解Bean的作用于,
// 若@Scope("prototype"),则Bean为原型类型;
// 若@Scope("singleton"),则Bean为单态类型;
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// 为注解Bean定义设置作用域,这里是singleton
abd.setScope(scopeMetadata.getScopeName());
// 为注解Bean定义生成Bean名称,这里是icoAppConfig2
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 处理注解Bean定义中的通用注解,主要是@Primary、@Lazy,@DependsOn、@Primary、@Role
// 处理完成之后processCommonDefinitionAnnotations中依然是把他添加到数据结构[adb]中
// @See 参加后面的processCommonDefinitionAnnotations说明
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
// 主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
// Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
if (qualifiers != null) { // 咱们这里面是null,所以先过
for (Class<? extends Annotation> qualifier : qualifiers) {
// 如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装,配时的首选
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
// 如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
// 则该Bean为预实例化
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
// 如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
// 个autowiring自动依赖注入装配限定符,该Bean在进autowiring
// 自动依赖注入装配时,根据名称装配限定符指定的Bean
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 根据注解Bean定义类中配置的作用域,创建相应的代理对象
// ScopedProxyMode需要结合Web去理解
// 见#applyScopedProxyMode说明
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 把上述的数据结构abd,注册给registry
// registry就是AnnotationConfigApplicationContext
// AnnotationConfigApplicationContext在初始化的时候通过调用父类的构造方法,
// 实例化了一个DefaultListableBeanFactory
// registerBeanDefinition里面就是把definitionHolder这个数据结构包含的信息注册到
// @See DefaultListableBeanFactory工厂,参考registerBeanDefinition 说明
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
processCommonDefinitionAnnotations说明
/**
* 作用:处理Bean定义中通用注解
* 输入参数一般是某个基于注解的bean定义(类级别或者方法级别bean定义),
* 以AnnotatedBeanDefinition类型存在的一个对象实例,
* 可能创建者已经设置了该对象的一些成员属性,但是更多的成员属性还存在于原始bean定义的元数据中,
* 该方法从原始bean定义的元数据中获取那些通用的注解信息:@Lazy,@DependsOn,@Role,@Description,
* 然后设置AnnotatedBeanDefinition实例相应的属性。
* 参数 abd : Bean定义
* 参数 metadata : 类型上的注解元数据信息
*/
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
// 如果Bean定义中有@Lazy注解,则将该Bean预实例化属性设置为@lazy注解的值
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"));
}
}
// 如果Bean定义中有@Primary注解,则为该Bean设置为autowiring自动依赖注入装配的首选对象
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
// 如果Bean定义中有@DependsOn注解,则为该Bean设置所依赖的Bean名称,
// 容器将确保在实例化该Bean之前首先实例化所依赖的Bean✨
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
applyScopedProxyMode说明
/** 根据作用域为Bean应用引用的代理模式 */
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
// 获取注解Bean定义类中@Scope注解的proxyMode属性值
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
// 如果配置的@Scope注解的proxyMode属性值为NO,则不应用代理模式
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
// 获取配置的@Scope注解的proxyMode属性值,如果为TARGET_CLASS
// 则返回true,如果为INTERFACES,则返回false
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
// 为注册的Bean创建相应模式的代理对象
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
registerBeanDefinition说明
根据断点,我们发现他调用的是GenericApplicationContext.registerBeanDefinition这个方法,然后这个方法,最终还是走到了DefaultListableBeanFactory里面,先看看beanDefinitionMap中有没有,然后判断一下hasBeanCreationStarted()🤔这个方法,发现都不符合,于是乎就是下面最终的代码,是的,上面噼里啪啦,就是为了下面三行
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
末尾添加一句,感谢子路老师的讲解,懂得人自然懂。
未完待续。。。