What is IoC

简单来说:

  • 控制:当前对象对其内部成员对象的控制权/获取组装对象的过程
  • 反转:上述的过程/控制权,交由专门的第三方组件(容器或者说平台)来管理

这种从具体对象手中,交出控制的做法,在解耦代码的同时提高了代码的可测试性。好处具体如下:

  1. 不用自己组装,拿来就用。
  2. 享受单例的好处,效率高,不浪费空间。
  3. 便于单元测试,方便切换mock组件。
  4. 便于进行AOP操作,对于使用者是透明的。
  5. 统一配置,便于修改。

Spring IoC

在spring中,IoC容器是实现这种模式的载体,它可以在对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方法调用的依赖。这种依赖注入是可以递归的,对象被逐层注入。

Spring IoC提供了一个基本的JavaBean容器,通过IoC模式管理依赖关系,并通过依赖注入和AOP切面增强了为JavaBean这样的POJO对象赋予事务管理、生命周期管理等基本功能。

IoC容器的设计

在Spring IOC 容器的设计当中,我们可以看到两个主要的容器系列(根据命名)

  • 实现了BeanFactory接口的简单容器系列,只实现了容器的最基本的功能;
  • ApplicationContext应用上下文,容器的高级形态,增加了许多面向框架的特性和应用环境的适配

BeanFactory

BeanFactory接口定义了IoC容器最基本的形式,并且提供了IoC容器所应该遵守的最基本的服务契约,同时,这也是我们使用IoC容器所应遵守的最底层和最基本的编程规范,这些接口定义勾画出了IoC的基本轮廓。

整个继承树是蛮复杂的,你也不需要所有都掌握,找核心类。现在来挑几个重点的BeanFactory说一下。

  • ListableBeanFactory,这个Listable的意思就是通过这个接口,可以获取多个bean,因为最顶层的BeanFactory接口的方法都是获取单个bean的。
  • ApplicationContext继承了HierarchicalBeanFactory,可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。
  • AutowireCapableBeanFactory这个名字中的Autowire大家非常熟悉,他就是用来自动装配bean用的,但是Application并没有继承它,不过不用担心,不适用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。
  • DefaultListableBeanFactory,实际上是把DefaultListableBeanFactory作为一个默认的功能完整的IoC容器来使用的。包含了基本IoC容器所具有的重要功能。

ApplicationContext

ApplicationContext是一个高级形态的IoC容器,ApplicationContext在BeanFactory的基础上集成了MessageSource, ApplicationEventPublisher, ResourcePatternResolver这几个接口,这些接口为ApplicationContext提供了以下BeanFactory不具备的新特性。

BeanFactory和Application的区别

  • BeanFactory是延迟加载
  • Application是立即加载,在启动时加载所有bean
  • ApplicationContext在启动时会自动注册BeanFactoryPostProcess和BeanPostProcess
  • BeanFactory不会自动注册这些接口
  • 如果使用的是普通的BeanFactory。那么事务和AOP等功能将不会生效(至少在不写其他额外代码的情况下生效)

BeanDefinition

在spring提供的基本ioc容器的接口定义和实现的基础上,spring通过定义BeanDefinition来管理基于spring应用中的各种对象以及它们之间的相互依赖关系。

BeanDefinition中保存了我们的bean信息,比如这个Bean指向的是哪个类,是否单例,是否延迟加载等等。


BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。

这些BeanDefinition就像是容器里装的水,有了这些基本数据,容器才能发挥作用。

Spring IoC容器初始化

以经典的ClassPathXmlApplicationContext为例,学习Spring IoC容器的初始化过程

Spring 容器初始化入口

启动容器,实际上是指实例化ApplicationContext的这个动作。只是在不同情况下可能有不同的表现形式。

  1. ClassPathXmlApplicationContext通过xml配置
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  1. AnnotationConfigApplicationContext通过java配置类
@Configuration
@ComponentScan("ric.study.demo.ioc")
public class BeanDemoConfig {public static void main(String... strings) {AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(BeanDemoConfig.class);System.out.println("Spring container started and is ready");...}
}

容器初始化 源码解析

以最经典的ClassPathXmlApplicationContext 上下文为起点,来描述整个过程。

ClassPathXmlApplicationContext的容器初始化可以大致分为下面几步:

  1. BeanDefinition的Resource定位
    这里的Resource定位是通过继承ResourceLoader获得的。
  2. 从Resource中解析、载入BeanDefinition
  3. BeanDefinition在ioc容器中注册

实例化这个上下文,就是启动ioc容器,那我们就从它的构造器入手。


入参的configLocations在这里就是xml配置文件的classpath。

setConfigLocations(configLocations),就是把一些带有占位符的地址解析成实际的地址。

再之后就是refresh()方法,容器的初始化就是从这里开始的,这里取名refresh,是因为容器启动之后,再调用refresh()会刷新ico容器。

refresh()的源码:

@Overridepublic void refresh() throws BeansException, IllegalStateException {//开局加个锁,不然refresh()还没有结束,你又来个启动或销毁容器的操作,那不就乱套了嘛synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.//准备工作,记录下容器启动的时间,标记”已启动“状态,处理配置文件中的占位符prepareRefresh();// Tell the subclass to refresh the internal bean factory./**这步完成之后,会生成一个BeanFactory,并将配置文件会解析成一个个BeanDefinition,注册到BeanFacotry中,这里的bean还没有初始化,只是配置信息提取出来了,注册就是将 beanName->BeanDefinition 保存到一个map中*/ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.//设置BeanFactory的类加载器,添加几个BeanPostprocessor,手动注册几个特殊的beanprepareBeanFactory(beanFactory);try {/**这里需要知道BeanFactoryPostProcessor这个知识点,Bean如果实现了此接口,那么容器初始化之后,Spring会负责调用里面的postProcessBeanFactory方法。这里是提供给子类的扩展点,到这里的时候,所有的bean都加载,注册完成,但是还没有初始化,具体的子类可以在这步的时候添加一些特殊的BeanFactoryPostProcessor的实现类。*/// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);//调用BeanFactoryPostProcessor各个实现类的postProcessBeanFactory()方法// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);/**注册BeanPostProcessor,此接口有两个方法, postProcessBeforeInitialization 和 postProcessAfterInitialization;这两个方法分别在bean初始化之前和初始化之后执行,注意,到这里bean还没初始化*/// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.// 初始化当前 ApplicationContext 的 MessageSource,国际化不是重点,不展开initMessageSource();// Initialize event multicaster for this context.// 初始化当前 ApplicationContext 的事件广播器,这里也不展开了initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.// 从方法名就可以知道,典型的模板方法(钩子方法),// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)onRefresh();// Check for listener beans and register them.// 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过registerListeners();// Instantiate all remaining (non-lazy-init) singletons./**重点,重点,重点!!!初始化所有的singleton beans,lazy-init除外*/finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.// 最后,广播事件,ApplicationContext 初始化完成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.// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源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();}}}

从上面源码流程中,挑以下几个进行分析:

  1. prepareRefresh()创建容器前的准备工作
  2. obtainFreshBeanFactory() 创建 BeanFactory,加载配置的bean并注册到BeanFactory中
  3. prepareBeanFactory(beanFactory) 对BeanFactory进行一些特征的设置工作
  4. finishBeanFactoryInitialization(beanFactory); 初始化所有的 singleton beans(DI的入口)

1. prepareRefresh()创建容器前的准备工作

protected void prepareRefresh() {// Switch to active.//记录启动时间,将 active 属性设置为 true,closed 属性设置为 false,它们都是 AtomicBoolean 类型this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);}else {logger.debug("Refreshing " + getDisplayName());}}// Initialize any placeholder property sources in the context environment.initPropertySources();// Validate that all properties marked as required are resolvable:// see ConfigurablePropertyResolver#setRequiredProperties//校验xml配置文件getEnvironment().validateRequiredProperties();// Store pre-refresh ApplicationListeners...if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);}else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// Allow for the collection of early ApplicationEvents,// to be published once the multicaster is available...this.earlyApplicationEvents = new LinkedHashSet<>();}

2. obtainFreshBeanFactory() 创建Bean容器,加载并注册bean

注意:这步之后,Bean并没有完成初始化,实际的实例并没有实例化。

源码位置:AbstractApplicationContext#obtainFreshBeanFactory()


点进去

点进去

源码:

 @Overrideprotected final void refreshBeanFactory() throws BeansException {/**如果ApplicationContext已经加载过BeanFactory,销毁所有的Bean,关闭BeanFactory注意点:应用中BeanFactory是可以有多个的,这里可不是说全局是否有BeanFactory而是说当前的ApplicationContext有没有BeanFactory!*/if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {// 初始化一个 DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();// 用于 BeanFactory 的序列化,一般人应该用不到吧...beanFactory.setSerializationId(getId());// 设置 BeanFactory 的两个重要属性,是否允许Bean覆盖,是否允许循环引用customizeBeanFactory(beanFactory);//加载BeanDefinition到BeanFacotory ,这个单独拉出来说loadBeanDefinitions(beanFactory);this.beanFactory = beanFactory;}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);}}

看到这里的时候,可以感觉到一个设计思路,ApplicationContext 继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的。

2.1. customizeBeanFactory() 设置BeanFactory的两个重要的属性

 protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {if (this.allowBeanDefinitionOverriding != null) {beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}if (this.allowCircularReferences != null) {beanFactory.setAllowCircularReferences(this.allowCircularReferences);}}

BeanDefinition的覆盖问题可能会有开发者碰到这个坑,就是在配置文件中定义bean的时候,使用了相同的id或name,默认情况下,allowBeanDefinitionOverriding 属性为null,如果在同一个配置文件中重复了,会抛错,但是如果不在一个配置文件中,会发生覆盖。

循环依赖也很好理解,A依赖B,B依赖A
默认情况下,Spring允许循环依赖,当然如果你在A的构造方法中依赖B,在B的构造方法中依赖A是不行的。

2.2. loadBeanDefinitions(beanFactory) 加载BeanDefinition

看一下这个方法的声明

/*** Load bean definitions into the given bean factory, typically through* delegating to one or more bean definition readers.* 将 bean 定义加载到给定的 bean 工厂,通常通过委托给一个或多个 bean 定义读取器。* @param beanFactory the bean factory to load bean definitions into* @throws BeansException if parsing of the bean definitions failed* @throws IOException if loading of bean definition files failed* @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader*/protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)throws BeansException, IOException;

通过xmlBeanDefinitionReader来载入Bean Definitions。

源码位置:AbstractXmlApplicationContext#loadBeanDefinitions()方法

 @Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.initBeanDefinitionReader(beanDefinitionReader);//重要的步骤,通过Reader去加载xml配置loadBeanDefinitions(beanDefinitionReader);}

源码位置:AbstractXmlApplicationContext#loadBeanDefinitions(XmlBeanDefinitionReader reader)方法

 /*** Load the bean definitions with the given XmlBeanDefinitionReader.* 看这句注释:this method is just supposed to load and/or register bean definitions.*    此方法只是应该加载和/或注册 bean 定义。*/protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {Resource[] configResources = getConfigResources();if (configResources != null) {reader.loadBeanDefinitions(configResources);}String[] configLocations = getConfigLocations();if (configLocations != null) {// 这个分支,通过路径名去获取Resource,会和上面的方法殊途同归reader.loadBeanDefinitions(configLocations);}}

源码位置:AbstractBeanDefinitionReader#loadBeanDefinitions(Resource… resources)

@Overridepublic int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {Assert.notNull(resources, "Resource array must not be null");int counter = 0;for (Resource resource : resources) {// 遍历解析XML文件,加载 BeanDefinitioncounter += loadBeanDefinitions(resource);}return counter;}

接下去的源码不细讲,这里载入分为两大步,

  1. 通过调用xml的解析器获取document对象,完成通用xml解析;
  2. 按照spring的bean规则进行解析。

2.3. 注册bean

虽然上面说了不讲xml解析成BeanDefinition的过程源码,但是上述的loadBeanDefinitions(resource)包含了我们关键的第三步,注册bean。这部分还是需要填一下的。

注意一下前面实例化Reader的代码,

XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);/*** Create new XmlBeanDefinitionReader for the given bean factory.* @param registry the BeanFactory to load bean definitions into,* in the form of a BeanDefinitionRegistry*/public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {super(registry);}

beanDefinitionReader 获取到 beanFactory 的引用,这个引用会在beanDefinition 被加载完毕要注册的时候使用到。可以看到是因为BeanDefinitionRegistry这个接口,赋予了BeanFactory注册BeanDefinition的特性。

具体执行“注册Bean”这一动作的源码,按照上述loadBeanDefinitions(resource)方法一直走下去的话是在DefaultBeanDefinitionDocumentReader#processBeanDefinition()方法中,

 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// Register the final decorated instance.// 注册BeanBeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}// Send registration event.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}

源码位置BeanDefinitionReaderUtils#registerBeanDefinition()

 /*** Register the given bean definition with the given bean factory.* @param definitionHolder the bean definition including name and aliases* @param registry the bean factory to register with* @throws BeanDefinitionStoreException if registration failed*/public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.// 注册String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.// 如果还有别名的,把别名全都注册一遍String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {// 到时候获取的时候,就是先把Alias转化成BeanName,再去获取对应的Beanregistry.registerAlias(beanName, alias);}}}

上面的registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());,

源码位置DefaultListableBeanFactory#registerBeanDefinition()

@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");if (beanDefinition instanceof AbstractBeanDefinition) {try {((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}// 注意哦,这里是有关 “允许Bean覆盖” 的逻辑代码// 记得这个配置 allowBeanDefinitionOverridingBeanDefinition oldBeanDefinition;// beanDefinitionMap 是存放所有BeanDefinition的容器oldBeanDefinition = this.beanDefinitionMap.get(beanName);// not null 说明,有重复名称的beanif (oldBeanDefinition != null) {if (!isAllowBeanDefinitionOverriding()) {// 判断是否允许覆盖,不允许直接抛异常throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +"': There is already [" + oldBeanDefinition + "] bound.");}else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {// 打下debug log...用框架定义的 Bean 覆盖用户自定义的 Beanif (this.logger.isWarnEnabled()) {this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +oldBeanDefinition + "] with [" + beanDefinition + "]");}}else if (!beanDefinition.equals(oldBeanDefinition)) {// 打下debug log...用新的 Bean 覆盖旧的 Beanif (this.logger.isInfoEnabled()) {this.logger.info("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}else {// 打下debug log...用同等的 Bean 覆盖旧的 Beanif (this.logger.isDebugEnabled()) {this.logger.debug("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}// 覆盖了this.beanDefinitionMap.put(beanName, beanDefinition);}else {// 判断是否有其他Bean已经开始初始化了if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)// 检测创建 Bean 阶段已经开启,需要对 beanDefinitionMap 进行并发控制synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;if (this.manualSingletonNames.contains(beanName)) {Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);updatedSingletons.remove(beanName);this.manualSingletonNames = updatedSingletons;}}}else {// Still in startup registration phase// 最最最正常的分支//  注册 到 容器中this.beanDefinitionMap.put(beanName, beanDefinition);// 这是一个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名字this.beanDefinitionNames.add(beanName);// 这是个 LinkedHashSet,代表的是手动注册的 singleton bean,// 注意这里是 remove 方法,到这里的 Bean 当然不是手动注册的// 手动指的是通过调用以下方法注册的 bean :// registerSingleton(String beanName, Object singletonObject)// 这不是重点,解释只是为了不让大家疑惑。Spring 会在后面"手动"注册一些 Bean,// 如 "environment"、"systemProperties" 等 bean,我们自己也可以在运行时注册 Bean 到容器中的this.manualSingletonNames.remove(beanName);}this.frozenBeanDefinitionNames = null;}if (oldBeanDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}}

以上,只是obtainFreshBeanFactory()的内容,到这里,BeanFactory也算是实例化完成了。

3. prepareBeanFactory(beanFactory)

此方法负责对BeanFactory进行一些特征的设置工作,这些在代码中都有体现。

 /*** Configure the factory's standard context characteristics,* such as the context's ClassLoader and post-processors.* @param beanFactory the BeanFactory to configure*/protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context's class loader etc.// BeanFactory 需要加载类,所以需要获得类加载器// 设置当前ApplicationContext的类加载器beanFactory.setBeanClassLoader(getClassLoader());// 内含 Spel 解释器,暂时不重要beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));// 注册属性编辑器,暂时不重要beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.// 添加一个ApplicationContextAwareProcessor,主要针对实现了Aware接口的Bean// 延伸知识:在Spring中我们自己的bean可以通过实现EnvironmentAware等一系列Aware接口,获取到Spring内部的一些对象。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 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* 那这里怎么没看到为 MessageSource 赋值呢?那是因为 MessageSource 被注册成为了一个普通的 bean*/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 的子类,// 这个postProcessor的作用就是将其添加到 listener 列表中,可以理解成:注册 事件监听器beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.// 这里涉及到特殊的 bean,名为:loadTimeWeaver,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()));}// Register default environment beans.// Spring 的“智能”操作,会帮我们默认注册一些有用的Bean//  如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}// 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}// 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}}

4. finishBeanFactoryInitialization(beanFactory) 实例化所有单例

这里会负责初始化所有的 singleton beans。

Spring 会在这个阶段完成所有的 singleton beans 的实例化。

到这里,应该说BeanFactory已经创建完成,并且所有实现了BeanFactoryPostProcessor接口的bean都已经初始化并且其中的postProcessBeanFactory()方法已经得到回调执行了,而且 Spring 已经“手动”注册了一些特殊的 Bean,如 environment、systemProperties 等。

剩下的就是初始化 singleton beans 了,我们知道它们是单例的,如果没有设置懒加载,那么 Spring 会在接下来初始化所有的 singleton beans。

源码位置:AbstractApplicationContext#finishBeanFactoryInitialization()

/*** Finish the initialization of this context's bean factory,* initializing all remaining singleton beans.*/protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.// 初始化"conversionService"的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));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.// 就是为了解析注解的值,没啥重点if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(new StringValueResolver() {@Overridepublic String resolveStringValue(String strVal) {return getEnvironment().resolvePlaceholders(strVal);}});}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.// 前面说过的,不是这里的重点String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {// 先初始化 LoadTimeWeaverAware 类型的beangetBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.// 看方法名就知道了,冻结所有BeanDefinition的元数据了// 没什么别的目的,因为到这一步的时候,Spring 已经开始预初始化 singleton beans 了,// 肯定不希望这个时候还出现 bean 定义解析、加载、注册。beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.// 开始初始化,进来看吧,重点在里面beanFactory.preInstantiateSingletons();}

源码位置:DefaultListableBeanFactory#preInstantiateSingletons()


@Overridepublic void preInstantiateSingletons() throws BeansException {if (this.logger.isDebugEnabled()) {this.logger.debug("Pre-instantiating singletons in " + this);}// copy 一个包含所有BeanName的集合副本List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);// 触发所有非懒加载的 singleton beans的初始化for (String beanName : beanNames) {// Bean 可能有继承parent的关系,获取合并后的RootBeanDefinitionRootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 非抽象、非懒加载的singletonsif (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// FactoryBean知识点,不了解的自己googleif (isFactoryBean(beanName)) {// FactoryBean 会在 beanName前面加前缀"&"final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {@Overridepublic Boolean run() {return ((SmartFactoryBean<?>) factory).isEagerInit();}}, getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}else {// 正常的bean都到这里来了,重点哦,里面进行初始化了// 调用链很复杂,单独拉出来讲,先继续getBean(beanName);}}}// 前面流程走完,说明所有的非懒加载singletonBean 完成了初始化// Trigger post-initialization callback for all applicable beans...// 看注释就懂了,如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的,// 那么在这里得到回调,忽略它吧。for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {smartSingleton.afterSingletonsInstantiated();return null;}}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}}
关于lazy-init

ApplicationContext实现的默认行为就是在启动时将所有的singleton bean进行提前实例化,提前实例化意味着作为初始化过程的一部分。有

的时候这种默认处理可能并不是你想要的,如果你不想让一个singleton bean在实现初始化的时候实例化,可以设置bean为延迟加载即可,

一个延迟初始化bean 将告诉IoC 容器是在启动时还是在第一次被用到时实例化。

需要说的是:如果一个bean被设置为延迟加载,而另一个非延迟加载的singleton bean依赖于它,那么当ApplicationContext提前实例化singleton bean时,必须确保singleton bean依赖的bean也预先被实例化,当然也包括延迟加载的bean,因此,如果ioc容器在启动的时候创建了那些被设置成延迟加载的singleton bean的实例,不要感到奇怪。

getBean() 做singleton bean的实例化操作

源码位置: AbstractBeanFactory#getBean(String name)

@Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}

doGetBean()

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {//获取真正的beanName//处理两种情况:1.将别名转化成beanname,2.把FactoryBean的前缀&去掉final String beanName = transformedBeanName(name);Object bean;//检测已经注册的bean,保证不重复创建// Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'");}}// 这个方法还是有点逻辑的// 如果目前获得的sharedInstance 不是FactoryBean,那bean就赋值成sharedInstance,直接返回// 如果是FactoryBean就返回FactoryBean创建的实例,bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// 直接翻译:创建过了此 beanName 的 prototype 类型的 bean,那么抛异常// We're assumably within a circular reference.// 往往是因为陷入了循环引用if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.// 检查下这个BeanDefinition是否存在BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.// 当前容器没有这个BeanDefinition,去parent 容器去找String nameToLookup = originalBeanName(name);if (args != null) { // Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 先初始化依赖的所有 Bean,这个很好理解。// 注意,这里的依赖指的是 depends-on 中定义的依赖String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {// 这里循环依赖概念不要紊乱了// 这里指的是通过 depends-on 定义造成的循环依赖,// 我们另外一种类成员式的循环引用Spring是支持的throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);getBean(dep);}}// Create bean instance.// 如果是 singleton scope 的,创建 singleton 的实例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {try {// 创建Bean的详情,等下拉出来单独说return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// 如果是 prototype scope 的,创建 prototype 的实例else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}// 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理// 这里非重点,我们的重点是singleton的创建else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// Check if required type matches the type of the actual bean instance.// 最后再检查下类型对不对,不对就抛异常了,对的话就返回if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {try {return getTypeConverter().convertIfNecessary(bean, requiredType);}catch (TypeMismatchException ex) {if (logger.isDebugEnabled()) {logger.debug("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}

doCreateBean()

步骤概览:

  1. 开始是单例的话,要先清除缓存;
  2. 实例化bean,将beanDefinition转换成Beanwrapper;
  3. 使用MergedBeanDefinitionPostProcessor,Autowired注解就是通过此方法实现类型的预解析;
  4. 解决循环依赖问题;
  5. 填充属性,将属性填充到bean实例中;
  6. 注册DisposableBean;
  7. 创建完成并返回

三个关注点:

  1. createBeanInstance() 实例化
  2. populateBean(); 属性装配
  3. initializeBean() 处理Bean初始化之后的各种回调事件
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {// Instantiate the bean.// 这个BeanWrapper是创建出来持有对象的BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {// 如果是singleton,先把缓存中的同名bean消除instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) // 关键代码,后面拉出来单独讲instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);mbd.resolvedTargetType = beanType;// Allow post-processors to modify the merged bean definition.// 涉及接口:MergedBeanDefinitionPostProcessor// 不是关键逻辑,不讲了synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.// 这里是为了解决循环依赖的,先把初步实例化的Bean实例的引用缓存起来,暴露出去,// 这个可以结合别的文章学习,面试题常考,我后面可能也会写boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}});}// Initialize the bean instance.Object exposedObject = bean;try {// 时序图中的一步,关键步骤,属性装配,前面的实例只是实例化,没有装配属性// 和前面的createBeanInstance一样会拉出来讲,继续看下去吧populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {// 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?// 这里就是处理 bean 初始化完成后的各种回调exposedObject = initializeBean(beanName, exposedObject, mbd);}}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}// 这个逻辑分支我一次性说完吧。// 如果该beanName对象已经注册单例模式,则从单例中获取,并判断获取到的bean实例(B)与BeanWrapper中的bean实例(A)是同一个实例,如果是,则返回A或者B,如果不是,则递归找出它的依赖bean。if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);// earlySingletonReference只有在检测到有循环依赖的情况下才会不为空if (earlySingletonReference != null) {if (exposedObject == bean) {// 两个是同一个引用,bean初始化完成exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.// 注册DisposableBean;try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

上一步的三个关注点,分开来讲:

1. createBeanInstance()

 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {// Make sure bean class is actually resolved at this point.// 解析出 ClassClass<?> beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}// 如果工厂方法不为空,则是用工厂方法初始化if (mbd.getFactoryMethodName() != null)  {// 相关知识点看另一篇文章关于FactoryBean的return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...// 如果不是第一次创建,比如第二次创建 prototype bean。// 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化// 所以注释说叫shortcutboolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {// 有已经解析过的构造方法resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}// 如果已经解析过则使用解析好的构造方法不需要再次锁定if (resolved) {if (autowireNecessary) {// 构造方法自动注入return autowireConstructor(beanName, mbd, null, null);}else {// 默认构造方法return instantiateBean(beanName, mbd);}}// Need to determine the constructor...// 判断是否采用有参构造函数// 构造器自动装配Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {return autowireConstructor(beanName, mbd, ctors, args);}// No special handling: simply use no-arg constructor.// 使用无参构造器return instantiateBean(beanName, mbd);}

2. populateBean(); 属性装配

入口方法: AbstractAutowireCapableBeanFactory#populateBean,它的作用是: 根据autowire类型进行autowire by name,by type或者是直接进行设置

 protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {PropertyValues pvs = mbd.getPropertyValues();if (bw == null) {if (!pvs.isEmpty()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}else {// Skip property population phase for null instance.return;}}// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.// 这里看注解是一个扩展点// InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改// 不是个常用的扩展点,这里不讲了boolean continueWithPropertyPopulation = true;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}}if (!continueWithPropertyPopulation) {return;}if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.// 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.// 通过类型装配if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);if (hasInstAwareBpps || needsDepCheck) {PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {// InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法// 代表能对属性值进行修改的能力// 其中一个很有用实现类提一下,AutowiredAnnotationBeanPostProcessor// 对采用@Autowired和@Value设值的就是这个BeanPostProcessor干的。// 不展开讲了,不然要讲不完了InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvs == null) {return;}}}}if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs);}}// 这里才是设置bean实例的属性值applyPropertyValues(beanName, mbd, bw, pvs);}

3. initializeBean() 处理Bean初始化之后的各种回调事件

 protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {invokeAwareMethods(beanName, bean);return null;}}, getAccessControlContext());}else {// 涉及到的回调接口点进去一目了然,代码都是自解释的// BeanNameAware、BeanClassLoaderAware或BeanFactoryAwareinvokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {// BeanPostProcessor 的 postProcessBeforeInitialization 回调wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {// init-methods// 或者是实现了InitializingBean接口,会调用afterPropertiesSet() 方法invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {// BeanPostProcessor 的 postProcessAfterInitialization 回调wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}

关于spring IoC 学习相关推荐

  1. Spring IOC学习心得之Bean对IOC容器的感知

    容器管理的Bean一般不需要了解容器的状态和直接使用Bean,但是在某些情况下,是需要在Bean中直接对IOC容器进行操作的,这时候,就需要在Bean中设定对容器的感知.Spring IOC也提供了该 ...

  2. Spring IOC 学习总结

    1 什么是IOC.DI IoC-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制 ...

  3. 【Spring】Spring IOC学习笔记

    Spring IOC Spring简介 Spring理念 使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架 Spring优点 Spring是一个轻量级的 控制反转(IOC) 和 面向切 ...

  4. Spring IoC 学习(3)

    前言 前面因为总结的累了,把IoC的两个步骤,只写了一半,就仅仅把容器启动的方面说了说,对于实例化的阶段,我前面并没有说,在这节中,准备讲一讲,实例化阶段. 生命周期 基础生命周期简图 这个部分,其实 ...

  5. Spring IOC学习心得之源码级分析ContextLoaderListener的作用(IOC容器初始化入口)

    ContextLoaderListener类是负责初始化IOC容器,即在我们的web项目中,这里就是IOC容器初始化的入口,由这个类启动IOC容器的初始化. 它配置在web.xml中,比如如下配置: ...

  6. Spring IOC学习心得之IOC容器的初始化过程

    注:本文大多数内容都是摘自<Spring技术内幕>这本书 简单来说,Ioc容器的初始化过程是在refresh()方法中启动的,包括BeanDefinition的Resource定位,载入和 ...

  7. Spring IOC学习心得之BeanPostProcessor,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware接口是如何起作用的

    1. 首先说下BeanPostProcessor接口中的两个方法,如下: package org.springframework.beans.factory.config;import org.spr ...

  8. hello word 程序 ——简单的spring ioc 学习

    转载于:https://www.cnblogs.com/yangweiguo123/p/10297758.html

  9. Spring IOC学习心得之注册bean的依赖关系

    registerDependentBean方法的解析(注册bean的依赖关系) 源码如下: public void registerDependentBean(String beanName, Str ...

最新文章

  1. Linux15-SELinux
  2. 【组队学习】【35期】深入浅出Pytorch
  3. iphone完整版的http上传请求协议
  4. 用Gmail备份多看的推送
  5. 一个简单的blog系统(九) 增加标签和标签页面
  6. 机器学习知识点(一)文本字符信息熵Java实现
  7. mysql5.7数据恢复_mysql 5.7.21 解压版通过历史data目录恢复数据的教程图解
  8. python学习必备知识点: 装饰器
  9. SSH登录太慢(等很久才提示输入密码)的问题
  10. python3和python2 优势_python3和python2的区别
  11. Mvc5 控制器,视图简单说明
  12. mysql or走索引吗_加了索引,mysql查询就一定会用吗?
  13. 凯恩帝k1000ti参数设置_KND1000TI系统参数
  14. 贾跃亭向全体债权人道歉!个人资产曝光:总额14亿美元,国内三套房
  15. SpringBoot Redis缓存 @Cacheable、@CacheEvict、@CachePut
  16. 组态王通过串口服务器通讯smart200_实例讲解通过代码调试串口通讯的方法
  17. 汇编语言王爽第四版 实验四(包括对【bx】,loop详解)
  18. php公网不能访问8080,linux启动tomcat外部浏览器不能访问8080端口解决方案
  19. 【rac asm扩容】在vmware workstation中配置集群(rac)的共享存储(磁盘)方法(流程)
  20. i5 13490f参数 怎么样 i5 13490f功耗 酷睿i513490f什么水平级别

热门文章

  1. 正向价值观和负向情商
  2. 缓存加速--Squid代理服务器应用(传统代理、透明代理)
  3. Pytorch中tensor.expand()和tensor.expand_as()函数
  4. Pytorch丨expand函数
  5. 瑞能微计量芯片RN2026的实用程序
  6. CDR2023软件最新版有哪些新增功能?
  7. 小米手机MIUI系统MIX4屏下光电指纹解锁时闪屏解决步骤办法
  8. 蓝桥杯国王的烦恼java,国王的烦恼 蓝桥杯
  9. 学习无止境,一起来学最好用的正则表达式大全
  10. python真假判断