在讲解spring ioc容器启动流程之前,我们先看下继承结构,方便梳理下文中大量的类、接口之间的关系。
这个是BeanFactory,作为顶层容器。
这个是我们常见的ApplicationContext
首先启动容器,有xml和注解这两种基本方式,我们下面的代码是基于注解方式,中间会穿插对xml方式的解释,大同小异,可以放心食用
SpringConfig类就是一个配置类
点进去看下这个注解容器的构造方法
无参构造方法实现
再看下是怎么注册咱们自定义的SpringConfig类的
跟着register(conmponentClasses)方法一路点进去,来到了doRegisterBean方法,这个方法的大致实现逻辑是首先生成一个beanDefinition,
然后解析下咱这个配置类SpringConfig的注解,看下是否是Primary、是否是lazy懒加载,接着new一个BeanDefinitionHolder,
这个holder其实就是对beanDefinition、beanName还有alias做了一层封装而已,这些完成后,开始注册这个beanDefinition
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { //生成一个abd AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(supplier); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); //解析bean上的注解 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)); } } } if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } //new一个BeanDefinitionHolder,这个holder封装了BeanDefinition、beanName、alias BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //注册bean,这里的registry是啥?就是AnnotationConfigApplicationContext //就是AnnotationConfigApplicationContext继承了GenericApplicationContext, //GenericApplicationContext里有个DefaultListableBeanFactory //DefaultListableBeanFactory有个registerBeanDefinition用于注册bean BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }
我们进入DefaultListableBeanFactory的registerBeanDefinition方法里看下注册beanDefinition的逻辑,可以看到,所谓的注册bean,本质上就是
把这个beanDefinition放到了DefaultListableBeanFactory的beanDefinitionMap里
到这里,我们的配置类SpringConfig.class已经注册到ioc容器里了(beanDefinition放到了DefaultListableBeanFactory的beanDefinitionMap里)
下面进入最最重点的AbstractApplicationContext的refresh()方法:
先看下obtainFreshBeanFactory,针对注解这种方式,这个方法完成后,会返回给我们一个beanFactory,也就是DefaultListableBeanFactory
下面是针对xml方式,refreshBeanFactory的具体实现逻辑
prepareBeanFactory,提前对我们的beanFactory做一些准备工作
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. //设置BeanFactory的类加载器,由于BeanFactory需要加载类,因此需要类加载器 //这里设置为当前ApplicationContext的类加载器 beanFactory.setBeanClassLoader(getClassLoader()); //设置BeanExpressionResolver if (!shouldIgnoreSpel) { beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); } beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. //添加一个BeanPostProcessor //实现了Aware接口的几个特殊的beans在初始化的时候,这个processor负责回调 /** * 如果在某个类里面想要使用Spring的一些东西,就可以通过实现XXXAware接口告诉Spring, * Spring看到后就会送过来,而接受的方式是通过实现接口唯一的方法setXXX. * 比如ApplicationContextAware、BeanNameAware */ beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //下面几行代码的意思是:如果某个bean依赖于以下几个接口的实现类,在自动装配时忽略它们 //Spring会通过其他方式来处理这些依赖 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.ignoreDependencyInterface(ApplicationStartup.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. /** * 下面几行就是为特殊的几个bean赋值,如果有bean依赖了以下几个,会注入这边相应的值 * "当前ApplicationContext持有一个BeanFactory",就是指这里的第一行 * ApplicationContext继承了ResourceLoader、ApplicationEventPublisher、MessageSource * 所以对于这几个,可以赋值为this,注意this是一个ApplicationContext * */ beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. //这个BeanPostProcessor也很简单,在bean实例化后,如果是ApplicationListener的子类 //那么将其添加到Listener列表中,可以理解为:注册事件监听器 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. //处理特殊bean"LoadTimeWeaver",这个不是重点 if (!IN_NATIVE_IMAGE && 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())); } // Register default environment beans. //spring帮我们默认注册一些有用的bean,我们也可以选择覆盖 //如果没有定义"environment"这个bean,那么Spring会"手动"注册一个 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()); } if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) { beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup()); } }
下面我们回到refresh方法,继续向下看,关注invokeBeanFactoryPostProcessor方法,调用BeanFactoryPostProcessor实现类的postProcessorBeanFactory方法,
invokeBeanFactoryPostProcessor方法执行完毕后,我们代码中自定义的bean都已经注册到beanFactory中了(包括我们自定义的beanPostProcessor,也作为bean注册到beanDefinitionMap中了),
下一步是注册beanPostProcessor(将processor放入到AbstractBeanFactory的beanPostProcessors这个列表里,后面初始化时从这个列表里取processor进行相应的方法回调)
下面我们进入重点中的重点finishBeanFactoryInitialization(beanFactory)方法,到这一步时,我们的beanFactory已经做好全部准备工作,bean已经注册到
工厂里,各种processor也已经注册,供接下来的bean初始化使用。这一步将完成bean的三大生命周期:实例化、属性装配、初始化
一路点进去,最终进入到AbstractBeanFactory的doGetBean方法,首先关注这里的getSingleton方法,这是spring中利用三级缓存解决循环依赖的关键
瞅一眼这个方法的具体实现:
先从一级缓存(singleObjects)取bean实例对象,没有则从二级缓存(earlySingletonObjects)取,还没有则从三级缓存(singletonFactories)取。
然后我们回到doGetBean方法,执行到createBean,实例化、属性装配、初始化也是在这个方法里完成的
进入到AbstractAutowireCapableBeanFactory的doCreateBean方法,这里包含了bean声明周期三大阶段:实例化、属性装配、初始化(在属性装配和初始化之间及初始化之后会有相应的aware、beanPostProcessor等执行),
这里出现一个BeanWrapper,这个wrapper就是根据beanDefinition完成实例化的bean的一层封装。
下面我们看实例化这一阶段是如何实现的
我们看下无参构造bean实例的方式instantiateBean():
这里进入到了SimpleInstantiationStrategy的instantiate方法(通过方法参数可知这是无参实例化策略),该类是实现了InstantiationStrategy接口,该接口有三个方法,分别按照无参、有参、工厂方法这三种策略来定义
最终通过反射或cglib代理,完成bean实例化,下面开始进入属性装配阶段, 让我们回到AbstractAutowireCapableBeanFactory的doCreateBean方法,
实例化之后,为了处理循环依赖问题,要先把已实例化但未属性装配的bean实例放入到三级缓存中。
所谓属性装配,即给bean实例的各种属性赋值(如果遇到属性依赖其他的bean,则先完成所依赖bean的实例化、属性装配、初始化),属性装配完毕后,进入初始化阶段,
在initializeBean方法里,我们可以看到,首先会执行实现了aware接口的方法回调,接着执行beanPostProcessor的before方法,然后执行初始化方法,最后回调beanPostProcessor的after方法。
这一步完成后,我们的refresh方法主要逻辑已经是实现完毕,整个spring ioc容器启动过程也基本完毕了。
补充:
在AbstractBeanFactory的createBean方法执行完毕后,我们的bean已经完成了实例化、属性装配、初始化,那为什么不直接返回bean实例而要执行这个getObjectForBeanInstance()方法?
这个方法是做什么的呢?
下面我们继续分析下:
这个主要是为了处理FactoryBean的
我们看下FactoryBean是什么,这个接口有三个方法,getObject用于返回T类型的实例,
isSingleton方法用来规定 Factory创建的的bean是否是单例。这里通过默认方法定义为单例。
getObjectType用来获取 T getObject()中的返回值 T 的具体类型
public interface FactoryBean<T> { String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType"; @Nullable T getObject() throws Exception; @Nullable Class<?> getObjectType(); default boolean isSingleton() { return true; }
好了,看了上面FactoryBean的介绍,我们可能还是不清楚这个FactoryBean到底是个什么东东?作用是什么?应用场景是什么?
假设我们业务中的一个TestBean实现了FactoryBean接口后,那么通过getBean(beanName)这种方式获取到的bean并不是我们这个TestBean,
而是TestBean所实现的getObject方法的返回值,当我们给beanName加上&前缀时,才会获取到真正的TestBean,
(所以说getBean方法返回的居然是我们实现FactoryBean接口定义的getObject方法返回值)
这就是FactoryBean的作用,那什么情况下可以用到FactoryBean呢?
一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,
如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。
Spring为此提供了一个FactoryBean的工厂类接口,用户可以通过实现该接口的getObject方法来定制实例化Bean的逻辑。