Java-第十五部分-源码解读-FactoryBean、接口实现类的管理和容器的启动过程

165 阅读6分钟

源码解读全文

FactoryBean

  • 保存的地方
  1. 真实BeanfactoryBeanObjectCache
  2. 工厂BeanSingletonObjects
  • 名称均为FactoryBean类名首字母小写
  • getBean(beanName)通过传入时的Name进行判断
  • 注册时,以类名正常注册到IOC中
  • 使用时,才会进行创建

自动注入过程

  • 当调用getTypeForFactoryBean,对于FactoryBean,会返回getObjectType的类型,进行匹配
  • FactoryBean返回的真实对象被注入另一个Bean时,如果发现此时this.cachedfalse,会调用value = resolveFieldValue(field, bean, beanName);需要在还没生成的Bean中找对应的BeanDefinition
  • 最终调用doGetBeanNamesForType,查看是否有需要被注入的类型,此时如果遍历到一个FactoryBean,且此时的FactoryBeanBeanName为普通的BeanName,那么就代表该Bean还是FactoryBean本身,没有生成真实要返回的对象,就调用FactoryBeangetObjectType进行类型匹配
  1. beanInstance instanceof FactoryBean遍历到factoryBean时,判定为正确
  • 类型匹配上之后,通过getBean获取,最终FactoryBeanRegistrySupportgetObjectFromFactoryBean调用object = doGetObjectFromFactoryBean(factory, beanName);,创建FactoryBean真正的对象,object = factory.getObject();,并进行赋值
  1. Object sharedInstance = getSingleton(beanName);
  2. sharedInstance如果不为null,还需要再尝试获取beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  3. 此时传入的FactoryBean本类,且名为FactoryBean,那么就不能通过isFactoryDereference进行判定,但是又为FactoryBean
  4. 尝试从factoryBeanObjectCache获取
  5. 最终通过object = getObjectFromFactoryBean(factory, beanName, !synthetic);创建并获取
  • 此时创建的Bean保存在factoryBeanObjectCache image.png

doGetBean

  • String beanName = transformedBeanName(name);进行名称转换,先获取当前单例池存在的bean,通过beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);进行判断

&实际上是一个标示,如果传入的name&,就代表取的是factoryBean本类

  • 最终通过isFactoryDereference进行判断,传入的name&直接返回 image.png
public static boolean isFactoryDereference(@Nullable String name) {
   return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
  • 否则,object = getCachedObjectForFactoryBean(beanName);,从factoryBeanObjectCache获取
protected Object getCachedObjectForFactoryBean(String beanName) {
   return this.factoryBeanObjectCache.get(beanName);
}

接口的实现类

  • 通过注解注册时,调用ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry进行注册BeanDefintion,注册的是实现类
  • getBean时,生成的也为实现类对应的BeanName,和实现类,此时单例池的为实现类的内容 image.png
  • 通过接口注入时,需要value = resolveFieldValue(field, bean, beanName);,进行findAutowireCandidates(beanName, type, descriptor);,查看类型匹配的类
  • 最终通过doGetBeanNamesForType遍历所有的beanNames,通过typeToMatch.isInstance(beanInstance)判定成功
// 确定是否是typeToMatch的实例
public boolean isInstance(@Nullable Object obj) {
   return (obj != null && isAssignableFrom(obj.getClass()));
}
  • 如果匹配到多个bean,通过autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);进行变量名的匹配

体现了在自动注入的流程中,先找到类对应上的,是其本类或其子类的实现类,再匹配名 image.png

  • 如果没有匹配上的,那么就会抛异常 image.png
  • 最终通过beanFactory.getBean(beanName);,获取匹配上的beanNameBean

因此,只能通过getBean实现类的beanName,才能获取对应的bean

容器的启动过程

  • 容器即是工厂,也是注册中心
  • AbstractBeanDefinition的构造打断点

过程

  • 启动ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
this(); //构造
register(componentClasses); //注册主配置类
refresh(); //刷新容器

构造器过程

  • 生成AnnotationConfigApplicationContext工厂,并进行组件装配
  • 准备读取器,并配置组件this.reader = new AnnotatedBeanDefinitionReader(this);
  1. 注册一个注解配置读取器AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
  2. 为工厂准备一些基础组件,各种解析器
  3. 注册核心组件BeanDefinition,需要后续通过getBean才能获取,(是否有JSR-250规范,通过是否引入相关jar包来判断),(处理配置类、自动装配、JSR250注解、jpa、事件方法监听、事件监听工厂)
  • 准备扫描器,this.scanner = new ClassPathBeanDefinitionScanner(this);,准备环境变量信息

注册主配置类

  • reader注册所有主配置类,this.reader.register(componentClasses);
  • doRegisterBean(beanClass, null, null, null, null);执行注册
  • AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);将配置类,转换为BeanDefinition
  • AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);解析bd中的注解,进行完善

Lazy/Primary/DependsOn/Role/Description

  • 如果配置了scopedProxy,最终返回的是配置类代理对象的BD
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  • 注册BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

刷新容器

  • 创建所有组件
  • 此时的BD image.png
  • 记录状态,StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
  • 准备上下文环境,prepareRefresh();
  1. 记录各种行为
  2. initPropertySources();模版方法,重写自行加载需要的信息;用来加载WebIOC容器时,加载当前应用的上下文,ApplicationContext
  3. getEnvironment().validateRequiredProperties();准备环境变量信息,没有则创建
  4. 存储子容器,早期运行的监听器、事件
  • 获取当前准备好的IOC空容器ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  • 预准备工厂,注册环境信息、后置处理器 prepareBeanFactory(beanFactory);
  1. 设置工厂必要的工具,类加载器、el解析器、资源加载器和解析器
  2. 注册Aware后置处理器,beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));,处理Aware的接口,并且忽略Aware簇的其他接口
  3. 注册可以解析到的依赖,把一些工厂中的对象放入this.resolvableDependencies.put(dependencyType, autowiredValue);
  4. 用于监听早期后置处理器的注册,beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  5. 往单例池中注册默认组件,工厂环境、JVM参数(Map)、系统环境变量(Map) image.png image.png
  • 后置处理工厂,postProcessBeanFactory(beanFactory);,模版方法,允许子类对工厂进行处理
  • 工厂增强,invokeBeanFactoryPostProcessors(beanFactory);
  1. 按顺序处理BeanDefinitionRegistryPostProcessor.class
  2. ConfigurationClassPostProcessor配置类的解析在此工作,Spring注解配置类的扫描过程,此时加载所有类的定义信息
  • 注册Bean的后置处理器registerBeanPostProcessors(beanFactory);
  1. 后置处理器们对IOC容器和Bean的影响
  2. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));重新注册了一个监听器的探测器,放到最后一个,前面prepareBeanFactory放过了,调整顺序
  • 结束标志beanPostProcess.end();
  • 初始化国际化组件initMessageSource();,mvc中发挥作用

检查是否有MESSAGE_SOURCE_BEAN_NAME组件或其定义信息,没有则初始化DelegatingMessageSource dms = new DelegatingMessageSource();

  • 初始化事件派发功能initApplicationEventMulticaster();

检查是否有APPLICATION_EVENT_MULTICASTER_BEAN_NAME组件或其信息,没有则初始化this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);

  • onRefresh();模版方法,留给子类重写,增强添加自己组件
  • 注册监听器registerListeners();
  1. String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);获取所有监听器
  2. 保存在派发器的集合中,getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
  3. 事件派发器进行事件派发时调用multicastEvent,遍历所有的监听器,异步执行监听方法
  4. 派发早期事件
  • 遍历并创建BeanfinishBeanFactoryInitialization(beanFactory);
  1. beanFactory.preInstantiateSingletons();执行创建逻辑
  2. 全部创建完成后,整体遍历,执行SmartInitializingSingleton.afterSingletonsInstantiated后初始化操作
  3. IOC重要的类、BeanDefinition注册流程和Bean实例化及属性赋值
  • 发布完成事件finishRefresh();
protected void finishRefresh() {
   // 清理资源缓存
   clearResourceCaches();
   // 初始化生命周期处理器,关注容器刷新环节
   // 检查是否包含`LIFECYCLE_PROCESSOR_BEAN_NAME`
   // 没有则创建 `new DefaultLifecycleProcessor();`
   initLifecycleProcessor();
   // 执行生命周期处理器的回调
   getLifecycleProcessor().onRefresh();
   // 发布事件
   // 派发器发布 `getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);`
   publishEvent(new ContextRefreshedEvent(this));
   // jconsole 暴露MBean端点信息,监控运行情况
   // `server.registerMBean(new LiveBeansView(),
      new ObjectName(mbeanDomain, MBEAN_APPLICATION_KEY, applicationName));` 往环境中注册
   if (!NativeDetector.inNativeImage()) {
      LiveBeansView.registerApplicationContext(this);
   }
}
  • finally中,重设缓存和设置标志位
resetCommonCaches();
contextRefresh.end();

finishBeanFactoryInitialization(beanFactory)

  • 初始化Bean
  • 设置类型转换组件
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
      beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
   beanFactory.setConversionService(
         beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
  • 值解析器 ${val}
if (!beanFactory.hasEmbeddedValueResolver()) {
   beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
  • LoadTimeWeaverAware加载时织入
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
   getBean(weaverAwareName);
}
  • 停止临时的ClassLoader
beanFactory.setTempClassLoader(null);
  • 缓存配置
beanFactory.freezeConfiguration();
  • 初始化所有懒加载的Bean
beanFactory.preInstantiateSingletons();

preInstantiateSingletons

  • 实例化单例Bean的处理
// 所有BeanDefinition的BeanNames集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
    //合并出BeanDefinition 有些bean存在继承,需要将父类的信息合并
   RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
   // 非抽象,是单例,非懒加载
   if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
      if (isFactoryBean(beanName)) { //工厂bean
          //MyBatis整合
          //将工厂bean放入IOC 前面`&`
          //通过调用`getObject()`的对象放入IOC,类型为`getObjectType`
         Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
         if (bean instanceof FactoryBean) {
            FactoryBean<?> factory = (FactoryBean<?>) bean;
            //允许提早创建,实现`SmartFactoryBean`重写方法
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
               isEagerInit = AccessController.doPrivileged(
                     (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                     getAccessControlContext());
            }
            else { 
               isEagerInit = (factory instanceof SmartFactoryBean &&
                     ((SmartFactoryBean<?>) factory).isEagerInit());
            }
            if (isEagerInit) {
               getBean(beanName);
            }
         }
      }
      else {
          //创建Bean
         getBean(beanName);
      }
   }
}