• spring ioc源码简析


     ClassPathXmlApplicationContext

    首先我们先从平时启动spring常用的ClassPathXmlApplicationContext开始解析

    ApplicationContext context = new ClassPathXmlApplicationContext(...)
    

    在这里插入图片描述

    // ClassPathXmlApplicationContext 133
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
    			throws BeansException {
    
    		// 1.注册父容器
    		super(parent);
    		// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
    		setConfigLocations(configLocations);
    		// 2.重建ApplicationContext(即销毁后创建)
    		if (refresh) {
    			refresh();
    		}
    }
    

    (1). 首先是注释的第一点,注册父容器的概念

    spring当中最常见的父子容器就是父容器spring和子容器springmvc了

    父子容器的作用在于,当我们尝试从子容器(即:Servlet WebApplicationContext)中获取一个bean时,如果找不到,则会委派给父容器(即Root WebApplicationContext)来查找,但是父容器找不到bean无法去子容器查找

    例子:
    子容器,如springmvc的controller可以找到spring扫描管理的service进而调用它,
    而spring的事务@Transactional却无法代理子容器管理的controller层,因为spring没有扫描controller,而且也无法从子容器中获取controller去创建代理类对象。

    关于父子容器:
    ①. 为什么要有父子容器?
    父子容器的作用主要是划分框架边界。
    在J2EE三层架构中,在service层我们一般使用spring框架, 而在web层则有多种选择,如spring mvc、struts等。因此,通常对于web层我们会使用单独的配置文件。例如在上面的案例中,一开始我们使用spring-servlet.xml来配置web层,使用applicationContext.xml来配置service、dao层。如果现在我们想把web层从spring mvc替换成struts,那么只需要将spring-servlet.xml替换成Struts的配置文件struts.xml即可,而applicationContext.xml不需要改变。

    ②. 为什么不能在Spring的applicationContext.xml中配置全局扫描?
    如果都在spring容器中,这时的SpringMVC容器中没有对象,所以加载处理器,适配器的时候就会找不到映射对象,映射关系,因此在页面上就会出现404的错误。
    因为在解析@ReqestMapping解析过程中,initHandlerMethods()函数只是对Spring MVC 容器中的bean进行处理的,并没有去查找父容器的bean。因此不会对父容器中含有@RequestMapping注解的函数进行处理,更不会生成相应的handler。所以当请求过来时找不到处理的handler,导致404。

    ③. 如果不用Spring容器,直接把所有层放入SpringMVC容器的配置spring-servlet.xml中可不可以?
    如果把所有层放入SpringMVC的。但是事务和AOP的相关功能不能使用。

    ④. 同时扫描?
    会在两个父子IOC容器中生成大量的相同bean,这就会造成内存资源的浪费。

    这里super调用到最后是调用ConfigurableApplicationContext接口的setParent方法,而我们配置的DispatcherServlet它继承了FrameworkServlet,而FrameworkServlet最后本质上继承了HttpServlet,也就是说它们会覆盖一个init初始化方法,在FrameworkServlet中调用的initServletBean就是覆盖了的初始化方法,而这个方法调用了initWebApplicationContext方法,其中第538行就使用了ConfigurableApplicationContext接口的setParent方法把spring的ApplicationContext注册为了它的父容器。

    ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
    
    if (!cwac.isActive()) {
    	if (cwac.getParent() == null) {
    		// line 538
    		cwac.setParent(rootContext);
    	}
    	......
    }
    

    你可能会好奇这里的rootContext,也就是spring的ApplicationContext是怎么获得的:

    WebApplicationContext rootContext =	
    WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    

    web应用程序启动时,tomcat会读取web.xml文件中的context-parm(含有配置文件的路径)和listener节点,接着会为应用程序创建一个ServletContext,为全局共享

    下面是配置文件:

    <!-- 1.启动Spring容器 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
    
    <!-- 2.SpringMvc的前端控制器-->
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>springMVC配置文件的路径</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    

    2.refresh

    这个是最核心的方法

    public void refresh() throws BeansException, IllegalStateException {
    
    		// 加个锁防止多个容器同时启动
    		synchronized (this.startupShutdownMonitor) {
    		
    			// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
    			prepareRefresh();
    
    			// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
          		// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
          		// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
             		// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
    				postProcessBeanFactory(beanFactory);
    
    				// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
             		// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
             		// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
    				registerBeanPostProcessors(beanFactory);
    
    				// 初始化当前 ApplicationContext 的 MessageSource
    				initMessageSource();
    
    				// 初始化当前 ApplicationContext 的事件广播器
    				initApplicationEventMulticaster();
    
    				// 从方法名就可以知道,典型的模板方法(钩子方法),
             		// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
    				onRefresh();
    
    				// 注册事件监听器,监听器需要实现 ApplicationListener 接口。
    				registerListeners();
    
    				 // 初始化所有的 singleton beans(lazy-init 的除外)
    				finishBeanFactoryInitialization(beanFactory);
    
    				// 最后,广播事件,ApplicationContext 初始化完成
    				finishRefresh();
    			}
    
    
    			catch (BeansException ex) {
    				if (logger.isWarnEnabled()) {
    					logger.warn("Exception encountered during context initialization - " +
    							"cancelling refresh attempt: " + ex);
    				}
    				// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
    				destroyBeans();
    				// 将active的flag重置
    				cancelRefresh(ex);
    				// 把异常往外抛
    				throw ex;
    			}
    			finally {
    				// 清理一下内存
    				resetCommonCaches();
    			}
    		}
    	}
    

    首先是启动容器前一些简单的准备工作

    (1). prepareRefresh

    记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符

    protected void prepareRefresh() {
    		// 记录时间,标记启动状态
    		this.startupDate = System.currentTimeMillis();
    		this.closed.set(false);
    		this.active.set(true);
    
    		if (logger.isInfoEnabled()) {
    			logger.info("Refreshing " + this);
    		}
    
    		// 初始化配置文件,例如填入占位符等
    		initPropertySources();
    
    		// 检查一下xml文件
    		getEnvironment().validateRequiredProperties();
    
    		
    		this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
    	}
    

    其次是获得新的BeanFactory

    (2).obtainFreshBeanFactory

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
       // 关闭旧的 BeanFactory (如果有),创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
       refreshBeanFactory();
    
       // 返回刚刚创建的 BeanFactory
       ConfigurableListableBeanFactory beanFactory = getBeanFactory();
       if (logger.isDebugEnabled()) {
          logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
       }
       return beanFactory;
    }
    

    (3).refreshBeanFactory

    @Override
    protected final void refreshBeanFactory() throws BeansException {
       // 如果 ApplicationContext 中已经加载过 BeanFactory 了,销毁所有 Bean,关闭 BeanFactory
       // 注意,应用中 BeanFactory 本来就是可以多个的,这里可不是说应用全局是否有 BeanFactory,而是当前
       // ApplicationContext 是否有 BeanFactory
       if (hasBeanFactory()) {
          destroyBeans();
          closeBeanFactory();
       }
       try {
          // 初始化一个 DefaultListableBeanFactory,为什么用这个,我们马上说。
          DefaultListableBeanFactory beanFactory = createBeanFactory();
          // 用于 BeanFactory 的序列化,我想不部分人应该都用不到
          beanFactory.setSerializationId(getId());
    
          // 下面这两个方法很重要
          // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
          customizeBeanFactory(beanFactory);
    
          // 加载 Bean 到 BeanFactory 中
          loadBeanDefinitions(beanFactory);
          synchronized (this.beanFactoryMonitor) {
             this.beanFactory = beanFactory;
          }
       }
       catch (IOException ex) {
          throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
       }
    }
    

    (4).DefaultListableBeanFactory

    看到这里的时候,我觉得读者就应该站在高处看 ApplicationContext 了,ApplicationContext 继承自BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是说其内部持有一个实例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory相关的操作其实是委托给这个实例来处理的。

    在这里插入图片描述

    (5).loadBeanDefinitions

    这个方法将根据配置,加载各个 Bean,然后放到 BeanFactory 中。
    这里看名称也可以注意到,我们所谓的bean就是BeanDefinition的实例
    所以接下来我们先讲BeanDefinition


    BeanDefinition

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
       // 我们可以看到,默认只提供 sington 和 prototype 两种,
       // 很多读者可能知道还有 request, session, globalSession, application, websocket 这几种,
       // 不过,它们属于基于 web 的扩展。
       String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
       String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    
       // 比较不重要,直接跳过吧
       int ROLE_APPLICATION = 0;
       int ROLE_SUPPORT = 1;
       int ROLE_INFRASTRUCTURE = 2;
    
       // 设置父 Bean
       // 一句话就是:继承父 Bean 的配置信息而已
       void setParentName(String parentName);
    
       // 获取父 Bean
       String getParentName();
    
       // 设置 Bean 的类名称,将来是要通过反射来生成实例的
       void setBeanClassName(String beanClassName);
    
       // 获取 Bean 的类名称
       String getBeanClassName();
    
    
       // 设置 bean 的 scope
       void setScope(String scope);
    
       String getScope();
    
       // 设置是否懒加载
       void setLazyInit(boolean lazyInit);
    
       boolean isLazyInit();
    
       // 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
       // 1.是 depends-on="" 属性设置的值。
       void setDependsOn(String... dependsOn);
    
       // 返回该 Bean 的所有依赖
       String[] getDependsOn();
    
       // 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
       // 如果根据名称注入,即使这边设置了 false,也是可以的
       void setAutowireCandidate(boolean autowireCandidate);
    
       // 该 Bean 是否可以注入到其他 Bean 中
       boolean isAutowireCandidate();
    
       // 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
       void setPrimary(boolean primary);
    
       // 是否是 primary 的
       boolean isPrimary();
    
       // 如果该 Bean 采用工厂方法生成,指定工厂名称。
       // 2.一句话就是:有些实例不是用反射生成的,而是用工厂模式生成的
       void setFactoryBeanName(String factoryBeanName);
       // 获取工厂名称
       String getFactoryBeanName();
       // 指定工厂类中的 工厂方法名称
       void setFactoryMethodName(String factoryMethodName);
       // 获取工厂类中的 工厂方法名称
       String getFactoryMethodName();
    
       // 构造器参数
       ConstructorArgumentValues getConstructorArgumentValues();
    
       // Bean 中的属性值,后面给 bean 注入属性值的时候会说到
       MutablePropertyValues getPropertyValues();
    
       // 是否 singleton
       boolean isSingleton();
    
       // 是否 prototype
       boolean isPrototype();
    
       // 如果这个 Bean 是被设置为 abstract,那么不能实例化,
       // 常用于作为 父bean 用于继承,其实也很少用......
       boolean isAbstract();
    
       int getRole();
       String getDescription();
       String getResourceDescription();
       BeanDefinition getOriginatingBeanDefinition();
    }
    

    ① depends-on

    首先是注释1提到的depends-on
    简单的说,depends-on就是被依赖的bean要先创建出来,两者之间并没有谁注入谁,谁不能没有谁这种强依赖关系,仅仅是决定创建的先后顺序而已。

    ② Bean 采用工厂方法生成

    这里捎带提一下,bean有三种生成方式:

    • 反射
    • 工厂方法
    • FactoryBean

    通常大家都认为只有反射这种,实际上还有两种,这里只介绍工厂方法,FactoryBean后面会提到

    这个是创建Stage类的Factory

    public class StageFactory {
        private static Stage instance;
        public static Stage getInstance() {
            if(instance == null){
                instance = new Stage();
            }
            return instance;
        }
    }
    

    然后在xml中配置bean即可

    <bean id="stage" class="com.linjie.staticfactory.StageFactory" factory-method="getInstance"></bean>
    


    接下来回到loadBeanDefinitions

    /** 我们可以看到,此方法将通过一个 XmlBeanDefinitionReader 实例来加载各个 Bean。*/
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
       // 给这个 BeanFactory 实例化一个 XmlBeanDefinitionReader
       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));
    
       // 初始化 BeanDefinitionReader,其实这个是提供给子类覆写的,
       // 我看了一下,没有类覆写这个方法,我们姑且当做不重要吧
       initBeanDefinitionReader(beanDefinitionReader);
       // 继续往下
       loadBeanDefinitions(beanDefinitionReader);
    }
    

    在经过一段漫长的调用栈,如下:
    在这里插入图片描述
    之后又经过一段漫长的调用栈的解析后( 这里就不一一画出来了 )
    把Dom树中的配置文件中的bean注册成BeanDefinition
    并注册一个beanName,BeanDefinition的map

    beanDefinitionMap.put(beanName, beanDefinition)
    

    和一个保存所有beanName的ArrayList:

    this.beanDefinitionNames.add(beanName);
    

    上面才刚刚讲完obtainFreshBeanFactory
    接下来是refresh方法中的其他方法,先贴一下refresh:

    public void refresh() throws BeansException, IllegalStateException {
    
    		// 加个锁防止多个容器同时启动
    		synchronized (this.startupShutdownMonitor) {
    		
    			// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
    			prepareRefresh();
    
    			// 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
          		// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
          		// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
             		// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
    				postProcessBeanFactory(beanFactory);
    
    				// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
             		// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
             		// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
    				registerBeanPostProcessors(beanFactory);
    
    				// 初始化当前 ApplicationContext 的 MessageSource
    				initMessageSource();
    
    				// 初始化当前 ApplicationContext 的事件广播器
    				initApplicationEventMulticaster();
    
    				// 从方法名就可以知道,典型的模板方法(钩子方法),
             		// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
    				onRefresh();
    
    				// 注册事件监听器,监听器需要实现 ApplicationListener 接口。
    				registerListeners();
    
    				 // 初始化所有的 singleton beans(lazy-init 的除外)
    				finishBeanFactoryInitialization(beanFactory);
    
    				// 最后,广播事件,ApplicationContext 初始化完成
    				finishRefresh();
    			}
    
    
    			catch (BeansException ex) {
    				if (logger.isWarnEnabled()) {
    					logger.warn("Exception encountered during context initialization - " +
    							"cancelling refresh attempt: " + ex);
    				}
    				// 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
    				destroyBeans();
    				// 将active的flag重置
    				cancelRefresh(ex);
    				// 把异常往外抛
    				throw ex;
    			}
    			finally {
    				// 清理一下内存
    				resetCommonCaches();
    			}
    		}
    }
    

    3. prepareBeanFactory

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
       // 设置 BeanFactory 的类加载器,我们知道 BeanFactory 需要加载类,也就需要类加载器,
       // 这里设置为加载当前 ApplicationContext 类的类加载器
       beanFactory.setBeanClassLoader(getClassLoader());
    
       // 设置 BeanExpressionResolver
       beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
       // 
       beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    
       // 1. 添加一个 BeanPostProcessor,这个 processor 比较简单:
       // 2. 实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调,
       // 这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
       // 注意:它不仅仅回调 ApplicationContextAware,
       //   还会负责回调 EnvironmentAware、ResourceLoaderAware 等,看下源码就清楚了
       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);
    
       /**
        * 下面几行就是为特殊的几个 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);
    
       // 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
       // 那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
       beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    
       // 这里涉及到特殊的 bean,名为:loadTimeWeaver,这不是我们的重点,忽略它
       // tips: ltw 是 AspectJ 的概念,指的是在运行期进行织入,这个和 Spring AOP 不一样,
       //    感兴趣的读者请参考我写的关于 AspectJ 的另一篇文章 https://www.javadoop.com/post/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()));
       }
    
       /**
        * 从下面几行代码我们可以知道,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());
       }
    }
    

    首先是注释1以及这部分代码多次提及的BeanPostProcessor

    ① BeanPostProcessor

    由名称可以得知,它是一个Bean的后置处理器,这里要注意和BeanFactoryPostProcessor区分开来,同样由名称可以得知,BeanFactoryPostProcessor是一个BeanFactory也就是bean工厂的后置处理器,这个我们后面会提到它,
    现在我们先关注BeanPostProcessor

    它是一个接口,有以下两个方法,分别是初始化前和初始化后的执行方法

    public interface BeanPostProcessor {
    	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    }
    

    具体这个初始化方法指的是什么方法,类似我们在定义bean时,定义了init-method所指定的方法

    这两个方法分别在init方法前后执行,需要注意一点,我们定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。

    既然是默认全部处理,那么我们怎么确认我们需要处理的某个具体的bean呢?

    可以看到方法中有两个参数。类型分别为Object和String,第一个参数是每个bean的实例,第二个参数是每个bean的name或者id属性的值。所以我们可以第二个参数,来确认我们将要处理的具体的bean。

    这个的处理是发生在Spring容器的实例化和依赖注入之后。

    ② ApplicationContextAwareProcessor

    在Spring当中有一个接口,名字叫做ApplicationContextAware
    一般而言spring中的bean是感知不到容器的存在的(为了解耦,这样你bean和容器不耦合,你可以把原来用spring扫描的bean改成用springmvc去扫描创建,不用修改bean的任何代码),所以当bean实现了ApplicationContextAware接口之后,bean就可以aware(感知)到容器,从而使用容器,进而从容器中获取其他bean

    那么,在什么场景下我们会需要继承ApplicationContextAware呢?

    在大部分情况下,容器中的bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean,或者一个非singleton bean要引用另外一个非singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例

    对于上面的问题,我们可以通过实现ApplicationContextAware接口让bean A能够感知bean 容器,并且在需要的时候通过使用getBean(“B”)方式向容器请求一个新的bean B实例。

    接下来我们要分析一下原因,为什么继承了ApplicationContextAware就能aware到容器呢?

    这里就要回到刚刚注释的地方了:

     beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    

    可以看到这里注册了一个上面提到的BeanPostProcessor的实现类,叫ApplicationContextAwareProcessor,就是这个类在bean初始化的时候给bean加入了能aware的功能

    那么它是怎么加的这功能?
    让我们进入ApplicationContextAwareProcessor看看源码,
    postProcessBeforeInitialization方法里,第91行里调用了invokeAwareInterfaces方法,所以我们应该看invokeAwareInterfaces方法:

    private void invokeAwareInterfaces(Object bean) {
    		if (bean instanceof Aware) {
    			if (bean instanceof EnvironmentAware) {
    				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    			}
    			if (bean instanceof EmbeddedValueResolverAware) {
    				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    			}
    			if (bean instanceof ResourceLoaderAware) {
    				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    			}
    			if (bean instanceof ApplicationEventPublisherAware) {
    				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    			}
    			if (bean instanceof MessageSourceAware) {
    				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    			}
    			// 看这里,这里为bean设置进去了一个applicationContext容器上下文对象
    			if (bean instanceof ApplicationContextAware) {
    				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    			}
    		}
    	}
    

    有了容器上下文对象,自然就可以getbean了。

    隔了这么久大家肯定又忘了refresh了,我这里再贴最后一次:

    @Override
    public void refresh() throws BeansException, IllegalStateException {
       // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
       synchronized (this.startupShutdownMonitor) {
    
          // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
          prepareRefresh();
    
          // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
          // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
          // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
          ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
          // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
          // 这块待会会展开说
          prepareBeanFactory(beanFactory);
    
          try {
             // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
             // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
    
             // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
             // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
             postProcessBeanFactory(beanFactory);
             // 3. 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
             invokeBeanFactoryPostProcessors(beanFactory);          
    
    
    
             // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
             // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
             // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。这里仅仅是注册,之后会看到回调这两方法的时机
             registerBeanPostProcessors(beanFactory);
    
             // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
             initMessageSource();
    
             // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
             initApplicationEventMulticaster();
    
             // 从方法名就可以知道,典型的模板方法(钩子方法),不展开说
             // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
             onRefresh();
    
             // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
             registerListeners();
    
             // 重点,重点,重点
             // 初始化所有的 singleton beans
             //(lazy-init 的除外)
             finishBeanFactoryInitialization(beanFactory);
    
             // 最后,广播事件,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);
    
             // 把异常往外抛
             throw ex;
          }
    
          finally {
             // Reset common introspection caches in Spring's core, since we
             // might not ever need metadata for singleton beans anymore...
             resetCommonCaches();
          }
       }
    }
    

    ③ BeanFactoryPostProcessor

    这里通过上面refresh方法的注释3来聊一下BeanFactoryPostProcessor,可以看到到invokeBeanFactoryPostProcessors方法这里,BeanFactoryPostProcessor中实现的postProcessBeanFactory方法都已经被执行了,也就是说
    BeanFactoryPostProcessor 在BeanPostProcessor之前执行
    也就是在bean初始化等之前就已经执行过了,那么接下来我们来了解一下
    BeanFactoryPostProcessor接口

    public interface BeanFactoryPostProcessor {
    
    	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    
    }
    

    通过实现这个接口,我们可以对ConfigurableListableBeanFactory进行操作,还记得ConfigurableListableBeanFactory 吗?
    在这里插入图片描述
    那么ConfigurableListableBeanFactory 能做什么呢,这个我还没研究过,这里先引用这样一句话:

    BeanFactoryPostProcessor是实现spring容器功能扩展的重要接口,例如修改bean属性值,实现bean动态代理等。很多框架都是通过此接口实现对spring容器的扩展,例如mybatis与spring集成时,只定义了mapper接口,无实现类,但spring却可以完成自动注入

    感兴趣可以自己研究一下mybatis的MapperScannerConfigurer了解一下,我之后可能也会分析mybatis源码

    接下来让我们再次回到正题,进入到finishBeanFactoryInitialization(beanFactory)中去

    4. finishBeanFactoryInitialization

    这里会负责初始化所有没有设置懒加载的 singleton beans

    // 初始化剩余的 singleton beans
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    
       // 1. 首先,初始化名字为 conversionService 的 Bean。
       // 什么,看代码这里没有初始化 Bean 啊!
       // 注意了,初始化的动作包装在 beanFactory.getBean(...) 中,这里先不说细节,先往下看吧
       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));
       }
    
       if (!beanFactory.hasEmbeddedValueResolver()) {
          beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
             @Override
             public String resolveStringValue(String strVal) {
                return getEnvironment().resolvePlaceholders(strVal);
             }
          });
       }
    
       // 先初始化 LoadTimeWeaverAware 类型的 Bean
       // 之前也说过,这是 AspectJ 相关的内容,放心跳过吧
       String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
       for (String weaverAwareName : weaverAwareNames) {
          getBean(weaverAwareName);
       }
    
       beanFactory.setTempClassLoader(null);
    
       // 没什么别的目的,因为到这一步的时候,Spring 已经开始预初始化 singleton beans 了,
       // 肯定不希望这个时候还出现 bean 定义解析、加载、注册。
       beanFactory.freezeConfiguration();
    
       // 开始初始化
       beanFactory.preInstantiateSingletons();
    }
    

    ① ConversionService

    最有用的场景就是,它用来将前端传过来的参数和后端的 controller 方法上的参数进行绑定的时候用。

    像前端传过来的字符串、整数要转换为后端的 String、Integer 很容易,但是如果 controller 方法需要的是一个枚举值,或者是 Date 这些非基础类型(含基础类型包装类)值的时候,我们就可以考虑采用 ConversionService 来进行转换。

    <bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
      <property name="converters">
        <list>
          <bean class="com.javadoop.learning.utils.StringToEnumConverterFactory"/>
        </list>
      </property>
    </bean>
    

    ConversionService 接口很简单,所以要自定义一个 convert 的话也很简单。

    下面再说一个实现这种转换很简单的方式,那就是实现 Converter 接口。

    来看一个很简单的例子,这样比什么都管用。

    public class StringToDateConverter implements Converter<String, Date> {
    
        @Override
        public Date convert(String source) {
            try {
                return DateUtils.parseDate(source, "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "HH:mm:ss", "HH:mm");
            } catch (ParseException e) {
                return null;
            }
        }
    }
    

    只要注册这个 Bean 就可以了。这样,前端往后端传的时间描述字符串就很容易绑定成 Date 类型了,不需要其他任何操作。

    进入最后一行的preInstantiateSingletons

    (1) preInstantiateSingletons

    我们就又回到 DefaultListableBeanFactory 这个类了

    @Override
    public void preInstantiateSingletons() throws BeansException {
       if (this.logger.isDebugEnabled()) {
          this.logger.debug("Pre-instantiating singletons in " + this);
       }
       // this.beanDefinitionNames 保存了所有的 beanNames
       List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    
       // 触发所有的非懒加载的 singleton beans 的初始化操作
       for (String beanName : beanNames) {
    
          // 合并父 Bean 中的配置,注意 <bean id="" class="" parent="" /> 中的 parent,用的不多吧,
          // 考虑到这可能会影响大家的理解,我在附录中解释了一下 "Bean 继承",不了解的请到附录中看一下
          RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    
          // 非抽象、非懒加载的 singletons。如果配置了 'abstract = true',那是不需要初始化的
          if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
             // 处理 FactoryBean
             if (isFactoryBean(beanName)) {
                // FactoryBean 的话,在 beanName 前面加上 ‘&’ 符号。再调用 getBean,getBean 方法别急
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                // 判断当前 FactoryBean 是否是 SmartFactoryBean 的实现,此处忽略,直接跳过
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                   isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                      @Override
                      public Boolean run() {
                         return ((SmartFactoryBean<?>) factory).isEagerInit();
                      }
                   }, getAccessControlContext());
                }
                else {
                   isEagerInit = (factory instanceof SmartFactoryBean &&
                         ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
    
                   getBean(beanName);
                }
             }
             else {
                // 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
                getBean(beanName);
             }
          }
       }
    
    
       // 到这里说明所有的非懒加载的 singleton 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>() {
                   @Override
                   public Object run() {
                      smartSingleton.afterSingletonsInstantiated();
                      return null;
                   }
                }, getAccessControlContext());
             }
             else {
                smartSingleton.afterSingletonsInstantiated();
             }
          }
       }
    }
    

    (2) getBean

    @Override
    public Object getBean(String name) throws BeansException {
       return doGetBean(name, null, null, false);
    }
    
    // 我们在剖析初始化 Bean 的过程,但是 getBean 方法我们经常是用来从容器中获取 Bean 用的,注意切换思路,
    // 已经初始化过了就从容器中直接返回,否则就先初始化再返回
    @SuppressWarnings("unchecked")
    protected <T> T doGetBean(
          final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
          throws BeansException {
       // 获取一个 “正统的” beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&’),
       // 一个是别名问题,因为这个方法是 getBean,获取 Bean 用的,你要是传一个别名进来,是完全可以的
       final String beanName = transformedBeanName(name);
    
       // 注意跟着这个,这个是返回值
       Object bean; 
    
       // 检查下是不是已经创建过了
       Object sharedInstance = getSingleton(beanName);
    
       // 这里说下 args 呗,虽然看上去一点不重要。前面我们一路进来的时候都是 getBean(beanName),
       // 所以 args 传参其实是 null 的,但是如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Bean
       if (sharedInstance != null && args == null) {
          if (logger.isDebugEnabled()) {
             if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("...");
             }
             else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
             }
          }
          // 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance,
          // 如果是 FactoryBean 的话,返回它创建的那个实例对象
          // (FactoryBean 知识,读者若不清楚请移步附录)
          bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
       }
    
       else {
          if (isPrototypeCurrentlyInCreation(beanName)) {
             // 创建过了此 beanName 的 prototype 类型的 bean,那么抛异常,
             // 往往是因为陷入了循环引用
             throw new BeanCurrentlyInCreationException(beanName);
          }
    
          // 检查一下这个 BeanDefinition 在容器中是否存在
          BeanFactory parentBeanFactory = getParentBeanFactory();
          if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
             // 如果当前容器不存在这个 BeanDefinition,试试父容器中有没有
             String nameToLookup = originalBeanName(name);
             if (args != null) {
                // 返回父容器的查询结果
                return (T) parentBeanFactory.getBean(nameToLookup, args);
             }
             else {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
             }
          }
    
          if (!typeCheckOnly) {
             // typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
             markBeanAsCreated(beanName);
          }
    
          /*
           * 稍稍总结一下:
           * 到这里的话,要准备创建 Bean 了,对于 singleton 的 Bean 来说,容器中还没创建过此 Bean;
           * 对于 prototype 的 Bean 来说,本来就是要创建一个新的 Bean。
           */
          try {
             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
             checkMergedBeanDefinition(mbd, beanName, args);
    
             // 先初始化依赖的所有 Bean,这个很好理解。
             // 注意,这里的依赖指的是 depends-on 中定义的依赖
             String[] dependsOn = mbd.getDependsOn();
             if (dependsOn != null) {
                for (String dep : dependsOn) {
                   // 检查是不是有循环依赖,这里的循环依赖和我们前面说的循环依赖又不一样,这里肯定是不允许出现的,不然要乱套了,读者想一下就知道了
                   if (isDependent(beanName, dep)) {
                      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                   }
                   // 注册一下依赖关系
                   registerDependentBean(dep, beanName);
                   // 先初始化被依赖项
                   getBean(dep);
                }
             }
    
             // 如果是 singleton scope 的,创建 singleton 的实例
             if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                   @Override
                   public Object getObject() throws BeansException {
                      try {
                         // 执行创建 Bean,详情后面再说
                         return createBean(beanName, mbd, args);
                      }
                      catch (BeansException ex) {
                         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);
                   // 执行创建 Bean
                   prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                   afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
             }
    
             // 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
             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>() {
                      @Override
                      public Object getObject() throws BeansException {
                         beforePrototypeCreation(beanName);
                         try {
                            // 执行创建 Bean
                            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;
          }
       }
    
       // 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了
       if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
          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;
    }
    

    (3) createBean

    这回我们要到一个新的类了 AbstractAutowireCapableBeanFactory,看类名,AutowireCapable?类名是不是也说明了点问题了。

    主要是为了采用 @Autowired 注解注入属性值

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
       if (logger.isDebugEnabled()) {
          logger.debug("Creating instance of bean '" + beanName + "'");
       }
       RootBeanDefinition mbdToUse = mbd;
    
       // 确保 BeanDefinition 中的 Class 被加载
       Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
       if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
          mbdToUse = new RootBeanDefinition(mbd);
          mbdToUse.setBeanClass(resolvedClass);
       }
    
       // 1.准备方法覆写,这里又涉及到一个概念:MethodOverrides,它来自于 bean 定义中的 <lookup-method /> 
       // 和 <replaced-method />
       try {
          mbdToUse.prepareMethodOverrides();
       }
       catch (BeanDefinitionValidationException ex) {
          throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
       }
    
       try {
          // 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理,
          // 在 《Spring AOP 源码分析》那篇文章中有解释,这里先跳过
          Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
          if (bean != null) {
             return bean; 
          }
       }
       catch (Throwable ex) {
          throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
       }
       // 重头戏,创建 bean
       Object beanInstance = doCreateBean(beanName, mbdToUse, args);
       if (logger.isDebugEnabled()) {
          logger.debug("Finished creating instance of bean '" + beanName + "'");
       }
       return beanInstance;
    }
    

    ① lookup-method

    这里还是引用刚刚那个问题:

    在大部分情况下,容器中的bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean,或者一个非singleton bean要引用另外一个非singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例

    其中除了之前提到的继承ApplicationContextAware以外,另一种解决方法就是使用lookup-method
    lookup method注入是spring动态改变bean里方法的实现。方法执行返回的对象,使用spring内原有的这类对象替换,通过改变方法返回值来动态改变方法。内部实现为使用cglib方法,重新生成子类,重写配置的方法和返回对象,达到动态改变的效果。

    package fiona.apple;
    
    public abstract class CommandManager {
     
        public Object process(Object commandState) {
            Command command = createCommand();
            command.setState(commandState);
            return command.execute();
        }
     
        protected abstract Command createCommand();
    }
    
    <bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
    </bean>
     
    <bean id="commandManager" class="fiona.apple.CommandManager">
        <lookup-method name="createCommand" bean="command"/>
    </bean>
    

    注意:由于采用cglib生成之类的方式,所以需要用来动态注入的类,不能是final修饰的;需要动态注入的方法,也不能是final修饰的。

    ② replaced-method

    replaced method注入是spring动态改变bean里方法的实现。需要改变的方法,使用spring内原有其他类(需要继承接口org.springframework.beans.factory.support.MethodReplacer)的逻辑,替换这个方法。通过改变方法执行逻辑来动态改变方法。内部实现为使用cglib方法,重新生成子类,重写配置的方法和返回对象,达到动态改变的效果。

    public class MyValueCalculator {
     
        public String computeValue(String input) {
            // some real code...
        }
     
        // some other methods...
     
    }
     
    /**
     * meant to be used to override the existing computeValue(String)
     * implementation in MyValueCalculator
     */
    public class ReplacementComputeValue implements MethodReplacer {
     
        public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
            // get the input value, work with it, and return a computed result
            String input = (String) args[0];
            ...
            return ...;
        }
    }
    
    <bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
        <!-- arbitrary method replacement -->
        <replaced-method name="computeValue" replacer="replacementComputeValue">
            <arg-type>String</arg-type>
        </replaced-method>
    </bean>
     
    <bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>
    

    接下来就是doCreateBean 方法了

    (4) doCreateBean

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
          throws BeanCreationException {
    
       // Instantiate the bean.
       BeanWrapper instanceWrapper = null;
       if (mbd.isSingleton()) {
          instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
       }
       if (instanceWrapper == null) {
          // 说明不是 FactoryBean,这里实例化 Bean,这里非常关键,细节之后再说
          instanceWrapper = createBeanInstance(beanName, mbd, args);
       }
       // 这个就是 Bean 里面的 我们定义的类 的实例,很多地方我直接描述成 "bean 实例"
       final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
       // 类型
       Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
       mbd.resolvedTargetType = beanType;
    
       // 建议跳过吧,涉及接口:MergedBeanDefinitionPostProcessor
       synchronized (mbd.postProcessingLock) {
          if (!mbd.postProcessed) {
             try {
                // MergedBeanDefinitionPostProcessor,这个我真不展开说了,直接跳过吧,很少用的
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
             }
             catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                      "Post-processing of merged bean definition failed", ex);
             }
             mbd.postProcessed = true;
          }
       }
    
       // 下面这块代码是为了解决循环依赖的问题,后面会讲到的
       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>() {
             @Override
             public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
             }
          });
       }
    
       // Initialize the bean instance.
       Object exposedObject = bean;
       try {
          // 这一步也是非常关键的,这一步负责属性装配,因为前面的实例只是实例化了,并没有设值,这里就是设值
          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);
          }
       }
    
       if (earlySingletonExposure) {
          // 
          Object earlySingletonReference = getSingleton(beanName, false);
          if (earlySingletonReference != null) {
             if (exposedObject == 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.
       try {
          registerDisposableBeanIfNecessary(beanName, bean, mbd);
       }
       catch (BeanDefinitionValidationException ex) {
          throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
       }
    
       return exposedObject;
    }
    

    可以看到这里面执行顺序是:创建 Bean 实例的 createBeanInstance 方法,依赖注入的 populateBean 方法,还有就是回调方法 initializeBean。


    5.createBeanInstance

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
       // 确保已经加载了此 class
       Class<?> 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);
       }
    
       // 如果不是第一次创建,比如第二次创建 prototype bean。
       // 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
       boolean 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);
          }
       }
    
       // 判断是否采用有参构造函数
       Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
       if (ctors != null ||
             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
             mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
          // 构造函数依赖注入
          return autowireConstructor(beanName, mbd, ctors, args);
       }
    
       // 调用无参构造函数
       return instantiateBean(beanName, mbd);
    }
    

    挑个简单的无参构造函数构造实例来看看:

    (1) instantiateBean

    protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
       try {
          Object beanInstance;
          final BeanFactory parent = this;
          if (System.getSecurityManager() != null) {
             beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
    
                   return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                }
             }, getAccessControlContext());
          }
          else {
             // 实例化
             beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
          }
          // 包装一下,返回
          BeanWrapper bw = new BeanWrapperImpl(beanInstance);
          initBeanWrapper(bw);
          return bw;
       }
       catch (Throwable ex) {
          throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
       }
    }
    

    我们可以看到,关键的地方在于:

    beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    

    (2) instantiate

    @Override
    public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
    
       // 如果不存在方法覆写,那就使用 java 反射进行实例化,否则使用 CGLIB,
       // 方法覆写 请参见附录"方法注入"中对 lookup-method 和 replaced-method 的介绍
       if (bd.getMethodOverrides().isEmpty()) {
          Constructor<?> constructorToUse;
          synchronized (bd.constructorArgumentLock) {
             constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
             if (constructorToUse == null) {
                final Class<?> clazz = bd.getBeanClass();
                if (clazz.isInterface()) {
                   throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                   if (System.getSecurityManager() != null) {
                      constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                         @Override
                         public Constructor<?> run() throws Exception {
                            return clazz.getDeclaredConstructor((Class[]) null);
                         }
                      });
                   }
                   else {
                      constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
                   }
                   bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                   throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
             }
          }
          // 利用构造方法进行实例化
          return BeanUtils.instantiateClass(constructorToUse);
       }
       else {
          // 存在方法覆写,利用 CGLIB 来完成实例化,需要依赖于 CGLIB 生成子类,这里就不展开了。
          // tips: 因为如果不使用 CGLIB 的话,存在 override 的情况 JDK 并没有提供相应的实例化支持
          return instantiateWithMethodInjection(bd, beanName, owner);
       }
    }
    

    到这里bean就实例化出来了,接下来就是赋值了:


    6. populateBean

    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
       // bean 实例的所有属性都在这里了
       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;
          }
       }
    
       // 到这步的时候,bean 实例化完成(通过工厂方法或构造方法),但是还没开始属性设值,
       // 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);
    
          // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
          if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
             autowireByName(beanName, mbd, bw, newPvs);
          }
    
          // 通过类型装配。复杂一些
          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 ibp = (InstantiationAwareBeanPostProcessor) bp;
                   // 这里有个非常有用的 BeanPostProcessor 进到这里: AutowiredAnnotationBeanPostProcessor
                   // 对采用 @Autowired、@Value 注解的依赖进行设值,这里的内容也是非常丰富的,不过本文不会展开说了,感兴趣的读者请自行研究
                   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);
    }
    

    7. initializeBean

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
       if (System.getSecurityManager() != null) {
          AccessController.doPrivileged(new PrivilegedAction<Object>() {
             @Override
             public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
             }
          }, getAccessControlContext());
       }
       else {
          // 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
          invokeAwareMethods(beanName, bean);
       }
    
       Object wrappedBean = bean;
       if (mbd == null || !mbd.isSynthetic()) {
          // BeanPostProcessor 的 postProcessBeforeInitialization 回调
          wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
       }
    
       try {
          // 处理 bean 中定义的 init-method,
          // 或者如果 bean 实现了 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;
    }
    

    8. 循环依赖

    循环依赖看这里:
    https://segmentfault.com/a/1190000015221968#articleHeader2
    其中的重点就是下面这幅图了:
    在这里插入图片描述
    有些东西没研究透也没时间研究,等之后可能会补上来的。

  • 相关阅读:
    20201014-Python学习笔记7
    20201013-kali学习笔记1
    uc-devtools使用
    H5混合应用测试流程
    小米手机开启开发者选项
    appium 元素定位工具介绍
    Appium常见元素操作
    问题:error: The instrumentation process cannot be initialized. Make sure the application under test does.
    获取appPackage与appActivity方法
    app测试定位方法
  • 原文地址:https://www.cnblogs.com/fatmanhappycode/p/12231187.html
Copyright © 2020-2023  润新知