本节继续上节文章,上节文章说到第三步实例化AnnotatedBeanDefinitionReader完毕,接下来说第四步:
4.实例化扫描器:ClassPathBeanDefinitionScanner
这里的扫描器仅仅是提供给开发者手动调用的,即AnnotationConfigApplicationContext对象.scan()方法。
5.注册bean配置类为BeanDefinition:register(annotatedClasses);
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//调用构造函数
this();
//注册我们的配置类
register(annotatedClasses);
//IOC容器刷新接口
refresh();
}
进入register(annotatedClasses)方法:
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
进入this.reader.register(annotatedClasses)方法:
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
进入registerBean(annotatedClass)方法:
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
进入doRegisterBean(annotatedClass, null, null, null)方法:
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//验证是否跳过注解,当不满足条件时,就会跳过
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,Descri ption
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解)
qualifiers永远都是空的,包括上面的name和instanceSupplier都是同样的道理
//但是spring提供了其他方式去注册bean,就可能会传入了
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));
}
}
}
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);
}
说明:
1.常规的方式注册配置类,除了第一个参数,其他参数都是默认值。
2.通过AnnotatedGenericBeanDefinition的构造方法,获得配置类的BeanDefinition,这和之前在注册ConfigurationClassPostProcessor类的时,也是通过构造方法去获得 BeanDefinition的,只不过当时是通过RootBeanDefinition去获得,现在是通过 AnnotatedGenericBeanDefinition去获得。
3.判断需不需要跳过注册,Spring中有一个@Condition注解,如果不满足条件,就会跳过这个类的 注册。
4.获得BeanName
5.解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary, DependsOn,Role,Description。
6. 限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他
7. 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中(方便传参)
8. 最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
//获取bean
String beanName = definitionHolder.getBeanName();
//注册bean定义
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
//注册bean名称的别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
至此,配置类注册完毕。
6.非常重要的一个方法 refresh():
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//调用构造函数
this();
//注册我们的配置类
register(annotatedClasses);
//IOC容器刷新接口
refresh();
}
进入refresh()方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//1:准备刷新上下文环境
prepareRefresh();
//2:获取告诉子类初始化Bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3:对bean工厂进行填充属性
prepareBeanFactory(beanFactory);
try {
// 第四:留个子类去实现该接口
postProcessBeanFactory(beanFactory);
// 调用我们的bean工厂的后置处理器.
invokeBeanFactoryPostProcessors(beanFactory);
// 调用我们bean的后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化国际化资源处理器.
initMessageSource();
// 创建事件多播器
initApplicationEventMulticaster();
// 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomat的.
onRefresh();
//把我们的事件监听器注册到多播器上
registerListeners();
//实例化我们剩余的单实例bean.
finishBeanFactoryInitialization(beanFactory);
// 最后容器刷新 发布刷新事件(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();
}
}
}
说明:
①prepareRefresh():刷新前准备工作,保存了容器的启动时间,启动标志等。
②ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory():把beanFactory取出来,XML模式下会在这里读取BeanDefinition。
③prepareBeanFactory():准备工作,为bean工厂添加了两个后置处理器,ApplicationContextAwareProcessor,ApplicationListenerDetector,还设置了忽略自动装配和允许自动装配的接口,如果不存在某个bean的时候,spring就自动注册singleton bean,还设置了bean表达式解析器等。进入prepareBeanFactory()方法,一探究竟:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置bean工厂的类加载器为当前application应用的加载器
beanFactory.setBeanClassLoader(getClassLoader());
//为bean工厂设置我们标准的SPEL表达式解析器对象StandardBeanExpressionResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//为我们的bean工厂设置了一个propertityEditor 属性资源编辑器对象(用于后面的给bean对象赋值使用)
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//注册了一个完整的ApplicationContextAwareProcessor 后置处理器用来处理ApplicationContextAware接口的回调方法
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
/**
* 当 Spring 将 Applie础onContextAwareProcessor 注册后,那么在 invokeAwarelnterfaces 方法中间接调用的 Aware 类已经不是普通的 bean 了 ,
* 如 ResourceLoaderAware、 ApplicationEventPublisher 等,那么当然需要在 Spring 做 bean 的依赖注入的时候忽略它们。
* 而 ignoreDependencyInterface 的作用正是在此
*/
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
/**
* 当注册了依赖解析后,例如当注册了对 BeanFactory.class 的解析依赖后,
* 当 bean 的属性注入的时候, 一旦检测到属性为 BeanFactory 类型便会将 beanFactory 的实例注入进去。
*/
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
//注册了一个事件监听器探测器后置处理器接口
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 处理aspectj的
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
//注册了bean工厂的内部的bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
//环境
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
//环境系统属性
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
//系统环境
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
说明:该方法主要做了如下操作:
① 设置了一个类加载器
②设置了bean表达式解析器
③ 添加了属性编辑器的支持
④添加了一个后置处理器:ApplicationContextAwareProcessor,此后置处理器实现了BeanPostProcessor接口
⑤设置了一些忽略自动装配的接口
⑥ 设置了一些允许自动装配的接口,并且进行了赋值操作
⑦在容器中还没有XX的bean的时候,帮我们注册beanName为XX的singleton bean