美文网首页
深度解析Spring源码

深度解析Spring源码

作者: Sorry2Me | 来源:发表于2020-12-27 13:07 被阅读0次

Spring容器启动

简单理解spring框架,首先就是一个框架,直白点讲就是提高效率的工具,好比工厂干活,以前是人机械式的工作,现在用上了机器,人只用去操作机器就行了。那么spring工具提供了一个大容器,每次工作前把需要的东西全放进去,用的时候去容器拿,不用像之前用的时候还要跑回去拿。框架终究只是一个工具,如果如何使用都不熟练,什么工具都不好上手,所以最重要的是基础。

大多数的框架都是一种套路,利用资源加载和反射,不断的加载配置文件,比如factories,handlers等等,value值往往就是对应需要类加载的全限定名,再不停地封装缓存信息,加载信息,监听信息等等,最后再去完成类加载之后的对象执行交互或者进一步封装。

首先是构建项目的目录,遵循了web开发的项目结构;使用spring框架,首先导入context核心包,包含了bean,core,expression等IoC功能

<!--core核心包-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.10.RELEASE</version>
</dependency>

所有的bean交给spring容器管理,所以"工作前"需要先启动容器,并将配置的bean放入到容器中:

第一种:ClassPathXmlApplicationContext,加载xml文件,然后解析生成Bean,注册Bean,通过getBean获取对象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DI的解析器,试验过程中注释掉也可以注入? -->
    <context:annotation-config />
    <!-- IoC的解析器 -->
    <context:component-scan base-package="cn.mytest.spring" />
</beans>

配置了注解方式去注册Bean,测试一下IoC和DI

--需要注入的bean
@Data
@Component
public class NameBean {
    private String prefix="张";
    private String suffix="三";
}
--IoC
@Component
public class TestBean {
    private String name;
    @Autowired
    NameBean nameBean;
    public String test(){
        this.name=nameBean.getPrefix()+nameBean.getSuffix();
        return name;
    }
}

--或者通过@Configuration+@Bean
@Configuration
public class ValidateBean {
    @Bean
    public ValidateBean get(){
        return new ValidateBean();
    }
}

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        TestBean testBean = (TestBean)context.getBean("testBean");
        System.out.println(testBean.test()); //张三
        Object validateBean = context.getBean("validateBean");        
    }

第二种:AnnotationConfigApplicationContext,初步实践得知,先注册类中贴有@Bean的实例,再直接根据类的简单名去注册bean,跟@Configuration无关

public class ValidateBean {
    @Bean
    public NameBean getName(){
        System.out.println(1111);
        return new NameBean();
    }
}

// 用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
//容器先后注册了NameBean,ValidateBean和TestBean
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ValidateBean.class,TestBean.class);
        Object testBean = applicationContext.getBean("testBean");        System.out.println(testBean);//1111 cn.mytest.spring.bean.TestBean@2d6eabae

第三种方式是在web容器启动时构建容器,可以通过配置监听器去初始化spring容器

   //ContextLoaderListener在创建时会默认查找WEB-INF/下的applicationContext.xml
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

最终都会走到父类AbstractApplicationContext的refresh方法中

ApplicationContext

首先web.xml会构建为一个ServletContext对象,所以web.xml的标签实例都可以从ServletContext中获取公共信息

ConfigurableApplicationContext是可配置的应用容器,比如ClassPathXmlApplicationContext加载xml配置的节点内容;而WebApplicationContext是依赖ServletContext提供的公共信息构建的容器,比如默认的XmlWebApplicationContext就同时实现了可配置的web容器

所以对于ConfigurableWebApplicationContext来说,首先是通过web.xml构建的ServletContext中实现一个WebApplicationContext应用,并在此基础上拓展应用配置(Java配置或XML配置)完善为一个可配置的web应用

以下图中继承体系只是其中之一

image

spring容器初始化的流程图

image

WebApplicationContext

spring容器启动中第三种方式通过初始化web容器,加载监听器ContextLoaderListener,用于监听web容器的生命周期,当web容器启动时就会触发,ServletContext就是整个web容器获取web.xml信息的公共源

对于SpringMVC WEB 启动时会初始化两个容器,一个是 ROOT WebApplicationContext;一个是 Servlet WebApplicationContext。这两个容器分别是在启动 ContextLoaderListener 和 DispatcherServlet 时初始化的。

--ContextLoaderListener 容器加载监听器
public void contextInitialized(ServletContextEvent event) {
    initWebApplicationContext(event.getServletContext());
}

servletConfig和servletContext简单理解,servletConfig就是每个servlet实例都有一个servletConfig;而一个web容器只有一个servletContext

initWebApplicationContext

而initWebApplicationContext初始化spring容器,和springMVC初始化容器调用的方法一致,所以在后者框架中将初始化容器放在servlet节点加载时去做的,而不是用监听器的方式

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    //判断servletContext容器中是否已经有创建好的app应用容器
    if (servletContext.getAttribute
        (WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
    }
    if (this.context == null) {
        //1.构建一个应用容器
        this.context = createWebApplicationContext(servletContext);
    }
    if (this.context instanceof ConfigurableWebApplicationContext) {
        ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
        //如果环境未激活,也就是未刷新之前设置父上下文、设置上下文id
        if(!cwac.isActive()) {
            //2.配置并刷新当前上下文环境
            this.configureAndRefreshWebApplicationContext(cwac, servletContext);
        }
    }
    //将应用容器添加到servletContext中   
    servletContext.setAttribute(WebApplicationContext.
                                ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
}

构建WebApplicationContext对象流程

image

createWebApplicationContext

从这里可以了解构建的是一个可配置的web容器ConfigurableWebApplicationContext

--ContextLoader
protected WebApplicationContext createWebApplicationContext
(ServletContext sc) {
    //根据配置确定构建自定义容器还是默认的容器XmlWebApplicationContext
    Class<?> contextClass = determineContextClass(sc);
    return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
}

determineContextClass

determineContextClass类加载需要构建的容器类,可以在web.xml中自定义容器,默认的容器就是XmlWebApplicationContext容器

protected Class<?> determineContextClass(ServletContext servletContext) {
    //String CONTEXT_CLASS_PARAM = "contextClass";表示在<context-param>标签中是否有配置的自定义的contextClass
    String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
    if (contextClassName != null) {
        return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
    }
    else {
        //defaultStrategies通过静态方法在类加载时已经添加了默认的参数
        //这个默认的就是XmlWebApplicationContext
        contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
        return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
    }
}

--配置自定义的Context
<context-param>
    <param-name>contextClass</param-name>
    <param-value>
        org.springframework.web.context.support.MyWebApplicationContext
    </param-value>
</context-param>

defaultStrategies默认策略,加载org.springframework.web.context包下的properties文件:

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
image

spring大量运用了加载资源文件的方式properties.load(inputStream)

--ContextLoader
private static final Properties defaultStrategies;

static {
      //String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";     
      ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
      defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
   }
}

Environment

Environment即当前应用运行时所处的环境,也可以叫做上下文,主要为应用程序环境的两个方面的支持:profiles 和properties,帮助Spring根据不同的环境配置加载不同的配置信息。

Profile

profile组,是一个以name名称命名的、逻辑上的、要被注册到容器中的BeanDefinition的集合。简单一点说,一个profile就代表一组BeanDefinition。比如当加载解析xml配置文件的时候,只有active=true激活的BeanDefinition才会被加载进容器,可以指定哪一个Profile是生效

Properties

Properties环境变量来自于各种PropertySource属性源,如:properties/yml文件、jvm虚拟机环境变量、操作系统环境变量、JNDI、Servlet上下文参数、自定义的属性对象。比如Springboot在启动时就将properties文件初始化加载到Environment中,并且增强profile后能够在不同环境下加载不同的配置

1. 当前目录的/config子目录
2. 当前目录
3. classpath下的/config目录
4. classpath路径根目录

configureAndRefreshWebApplicationContext

将servletContext封装到当前容器,初始化ConfigurableEnvironment环境容器,加载初始化配置类,初始化应用容器

protected void configureAndRefreshWebApplicationContext(
    ConfigurableWebApplicationContext wac, ServletContext sc) {
    //配置应用程序id
    //id:org.springframework..support.XmlWebApplicationContext@710c986
    //@后面是hash值避免冲突,容器每次构建时都是唯一
    if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
        //首先找web.xml中<context-param>配置:param-name为contextId
        String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
        if (idParam != null) {
            wac.setId(idParam);
        }else {
            //默认id:org.springframework.web.context.WebApplicationContext:
            wac.setId(ConfigurableWebApplicationContext
                      .APPLICATION_CONTEXT_ID_PREFIX +
                      ObjectUtils.getDisplayString(sc.getContextPath()));
        }
    }
    wac.setServletContext(sc);
     /**
     * 设置要加载的配置文件路径
     * <context-param>
     *      <param-name>contextConfigLocation</param-name>
     *      <param-value>classpath:spring.xml</param-value>
     *  </context-param>
     */
    String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
    if (configLocationParam != null) {
        wac.setConfigLocation(configLocationParam);
    }
    //Environment用于选择应用程序需要运行的环境,子类ConfigurableEnvironment:提供设置激活的 profile 和默认的 profile 的功能以及操作 Properties 的功能
    ConfigurableEnvironment env = wac.getEnvironment();
    if (env instanceof ConfigurableWebEnvironment) {
        //ConfigurableWebEnvironment兼具了cofig和web属性的enviroment
        //web属性是封装了servlet环境,cofig是封装PropertySource(properties)
        ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
    }
    //初始化Initializer类,在容器刷新之前就加载的类,实现ApplicationContextInitializer完成自定义加载
    customizeContext(sc, wac);
    //刷新环境和容器完成容器的启动
    wac.refresh();
}

ObjectUtils.identityToString方法:

public static String identityToString(Object obj) {
    return obj.getClass().getName() + "@" + getIdentityHexString(obj);
}

initPropertySources初始化PropertySources容器,PropertySource接口类似一个Map,PropertySources的实现类MutablePropertySources用链表实现存放PropertySource

initPropertySources最终由WebApplicationContextUtils.initServletPropertySources实现,servletContext是web容器变量,有web.xml的配置信息(比如context-param);ServletConfig保存着servlet节点对应容器的配置信息(比如 init-param),这个初始化其实是想把servletContext,一个servletConfig这两个对象给存到容器的propertySources容器里去

public class MutablePropertySources implements PropertySources {
    private final List<PropertySource<?>> propertySourceList;
    ...

customizeContext

applicationcontextInitializer初始化加载,有四种实现方式:

1.加载context-param节点中自定义配置的InitializerClasses,一般用不到

protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
     /**
     *
     * globalInitializerClasses 代表所有的web application都会应用
     * contextInitializerClasses 代表只有当前的web application会使用
     * 配置自定义的globalInitializerClasses/contextInitializerClasses:
     *  <context-param>
     *      <param-name>contextInitializerClasses</param-name>
     *      <param-value>com..MyContextInitializerClasses</param-value>
     *  </context-param> 
     */   List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> 
    initializerClasses = determineContextInitializerClasses(sc);
        ...
    //自定的ApplicationContextInitializer再调用initialize()方法        
    for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
         initializer.initialize(wac);
     }

2.加载spring.factories配置

ApplicationContextInitializer容器初始化接口在springboot中频繁用到,refresh之前对ConfiurableApplicationContext的做进一步的设置和处理,在springboot中一键启动时加载所有需要初始化的配置类,比如start相关包中META-INF/spring.factories中配置

image

3.mian函数中添加:application.addInitializers(new MyApplicationContextInitializer());

@SpringBootApplication
public class MySpringBootApplication {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(MySpringBootApplication.class);
        application.addInitializers(new MyApplicationContextInitializer());
        application.run(args);
    }
}

public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        System.out.println(Thread.currentThread().getName());
    }
}

4.配置文件中配置:context.initializer.classes=xxx.MyApplicationContextInitializer

image

启动容器之后进行初始化

image

applicationcontextInitializer排序问题:@Order(Ordered.HIGHEST_PRECEDENCE)

image

refresh

简单理解,这一步就是实现构建应用容器,加载诸如xml配置,注解方式配置,java配置(@Configuration)方式配置初始化添加到容器中

除了以上构建的web容器,还有注解方式构建的容器,xml方式构建容器,目前理解是这些容器和web容器都是隔离可独立运行的

-- 不依赖web服务器构建容器
public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        Object testVo = context.getBean("tempVo");
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="tempVo" class="com.pingan.mytest.vo.TempVo"/>

</beans>

refresh()方法和方法内的具体实现都在AbstractApplicationContext类

--AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
    //简单来说就是不允许同时进行refresh
    synchronized (this.startupShutdownMonitor) {
        //预处理,初始化容器的设值
        prepareRefresh();
        //根据不同容器的实现解析beanDefinition并添加到beanFactory 
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        //填充BeanFactory:添加处理器,比如spring语言处理器等等,封装几个特殊的bean等
        prepareBeanFactory(beanFactory);
        try {        
            // 容器后处理器
            postProcessBeanFactory(beanFactory);
            // 激活BeanFactoryPostProcessor处理器
            invokeBeanFactoryPostProcessors(beanFactory);
            //注册除了beanFactory中的 beanPostProcessors之外其他的BeanPostProcessor,
            //将这些处理器通过beanFactory.addBeanPostProcessor(postProcessor)
            //添加到beanFactory,并将原处理器放在链尾
            registerBeanPostProcessors(beanFactory);
            // 初始化MessageSource接口用于支持信息的国际化和包含参数的信息的替换
            initMessageSource();
            // 初始化事件广播器ApplicationEventMulticaster
            initApplicationEventMulticaster();
            // 留给子类初始化其他Bean(空的模板方法)
            onRefresh();
            // 将listener添加到广播器中
            registerListeners();
            // 初始化其他单例Bean(非延迟加载的)
            finishBeanFactoryInitialization(beanFactory);
            // 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知
            finishRefresh();
        }
        catch (BeansException ex) {
            // 销毁已经创建的Bean
            destroyBeans();
            // 重置active设值为false
            cancelRefresh(ex);
            throw ex;
        }
        finally {
            resetCommonCaches();
        }
    }
}

preRefresh

preRefresh预刷新,其中initPropertySources方法的web容器实现是将所有servletConfig和servletContext实例封装到web环境的propertySources容器中

protected void prepareRefresh() {
    //封装servletContext和所有servletConfig到enviroment中
    initPropertySources();
    //验证在spring启动的时候自定义配置的环境变量必须存在,重写initPropertySources方法:比如getEnvironment().setRequiredProperties("xx");设值
    getEnvironment().validateRequiredProperties();
    //初始化earlyApplicationListeners,applicationListeners
    ...
}

earlyApplicationListeners,applicationListeners都封装在ApplicationContext的子类AbstractApplicationContext中,所以如果要添加这些需要注入它的子类

@Autowired
AbstractApplicationContext applicationContext;

applicationContext.getBean("testController");
applicationContext.addApplicationListener(...);

obtainFreshBeanFactory

解析并装载普通Bean,比如xml容器将所有 Spring 配置文件中的 bean 标签解析成bean,并构建成一个个 BeanDefinition,添加到 BeanFactory 中

这里涉及的BeanFactory,其接口是用于管理Bean,而在ApplicationContext继承实现图中可以了解到,ApplicationContext是BeanFactory的一种应用容器Bean管理工厂,而ApplicationContext中实际上又封装了BeanFactory

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
    //是否允许 Bean 覆盖
    private Boolean allowBeanDefinitionOverriding;
    //是否允许循环引用
    private Boolean allowCircularReferences;
    private DefaultListableBeanFactory beanFactory;
    ...
}

--- DefaultListableBeanFactory
//封装的beanDefinitionMap
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);

refreshBeanFactory刷新BeanFactory,这个DefaultListableBeanFactory继承实现了ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory三个功能;BeanFactory封装到config容器中,将解析出的BeanDefinition封装到BeanFactory中

--AbstractRefreshableApplicationContext
protected final void refreshBeanFactory() throws BeansException {
    //清除原BeanFactory
    ...
    //新建一个默认的BeanFactory,封装了当前的config容器
    DefaultListableBeanFactory beanFactory = createBeanFactory();
    //前面有设值过:org.springframework.web.context.WebApplicationContext:
    beanFactory.setSerializationId(getId());
    //设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
    customizeBeanFactory(beanFactory);
    //加载BeanDefinition,将bean添加到beanDefinitionMap中(具体在后面目录中)
    loadBeanDefinitions(beanFactory);
    synchronized (this.beanFactoryMonitor) {
        this.beanFactory = beanFactory;
    }
}

prepareBeanFactory

封装一些特殊的bean和处理器等,简单理解就是往BeanFactory中设值,目前从这里并无法判定每个处理器的作用,所以主要作用是封装后续所需的对象

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 添加classLoader类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 添加beanFactory的表达式语言处理器,默认可以使用#{xxx.xxx}的形式来调用相关属性值
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 添加默认的PropertyEditors属性编辑器,实现PropertyEditorSupport接口可以自定义属性编辑器
    //Set<PropertyEditorRegistrar> propertyEditorRegistrars
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    //添加一个bean后置处理器BeanPostProcessor
    //封装在List<BeanPostProcessor> beanPostProcessors
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    //添加忽略bean 依赖于以下几个接口的实现类,Spring 会通过其他方式来加载这些依赖
    //实现了ApplicationContextAware通过setter注入
    //Set<Class<?>> ignoredDependencyInterfaces
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);   
    ...
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    // 添加几个自动装配的特殊Bean,比如BeanFactory和ApplicationContext
    //Map<Class<?>, Object> resolvableDependencies
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    ...
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    //添加的这个处理器作用就是将实现了接口ApplicationListener的bean添加到beanFactory
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    //如果存在bean名称为loadTimeWeaver的bean则注册一个BeanPostProcessor,aspctj功能
    //类加载期织入切面,在xml配置<context:load-time-weaver aspectj-weaving="autodetect"/>
    //解析context的namespace会解析这个LTW
    if (beanFactory.containsBean("loadTimeWeaver")) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        //ClassLoader tempClassLoader
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // 注册默认的系统环境bean,environment,systemProperties,systemEnvironment
    if (!beanFactory.containsLocalBean("environment")) {
        //就是封装到BeanFactory中多个集合中:singletonObjects,registeredSingletons等
        beanFactory.registerSingleton("environment", getEnvironment());
    }
    ...
}

postProcessBeanFactory

有多个实现,也可以自定义实现,以AbstractRefreshableWebApplicationContext容器为例

--AbstractRefreshableWebApplicationContext
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //将ServletContext传递给实现ServletContextAware接口的bean
    beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
    //忽略实现了以下2个接口的实现类的注册,添加到ignoredDependencyInterfaces
    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
    //注册 WEB 应用特定的域(scope),比如: request session response application等.
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    //注册 WEB 应用特定的 Environment bean,比如contextAttributes等
    //registerSingleton servletContext和servletConfig
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

注册 WEB 应用特定的域(scope)

public static void registerWebApplicationScopes
(ConfigurableListableBeanFactory beanFactory, ServletContext sc) {
    //将scope添加到beanFactory中Map<String, Scope> scopes
    beanFactory.registerScope("request", new RequestScope());
    //RequestScope和SessionScope都是空实现
    beanFactory.registerScope("session", new SessionScope());
    //ServletContextScope封装了ServletContext
    ServletContextScope appScope = new ServletContextScope(sc);
    beanFactory.registerScope("application", appScope);
    //将ApplicationScope作为ServletContext的属性进行注册
    sc.setAttribute(ServletContextScope.class.getName(), appScope);
    //注册域的bean,封装到resolvableDependencies映射中
    beanFactory.registerResolvableDependency(ServletRequest.class, new WebApplicationContextUtils.RequestObjectFactory());
    ...
}

invokeBeanFactoryPostProcessors

激活context中Bean工厂后置处理器beanFactoryPostProcessors

--自定义实现ApplicationContextInitializer
public class MyTestInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
       //将自定义的实现BeanFactoryPostProcessor接口的处理器添加到context中
       configurableApplicationContext.addBeanFactoryPostProcessor(xx);
    }
}

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    //getBeanFactoryPostProcessors获取的是Application的beanFactoryPostProcessors
    //在customizeContext 方法就是实现自定义添加BeanFactoryPostProcessor
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
    ...
}

initApplicationEventMulticaster

applicationEventMulticaster用于事件发布,具体实现AbstractApplicationEventMulticaster还实现了BeanClassLoaderAware, BeanFactoryAware 接口,用于初始化类加载器及bean容器

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    //判断是否已存在注册的applicationEventMulticaster
    if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
        this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
    } else {
        //默认SimpleApplicationEventMulticaster并注册
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
    }
}

---AbstractApplicationEventMulticaster
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
    // 监听器回收器(注册器)封装ApplicationListener 的所有实现bean
    private final AbstractApplicationEventMulticaster.ListenerRetriever defaultRetriever = new AbstractApplicationEventMulticaster.ListenerRetriever(false);
    ...
    //类加载和beanFactory
    private ClassLoader beanClassLoader;
    private ConfigurableBeanFactory beanFactory;
    // 单例对象的缓存: Map<String, Object> singletonObjects
    private Object retrievalMutex;
}

SimpleApplicationEventMulticaster 还封装了线程池,在refresh方法中最终会通过finishRefresh方法调用实现广播事件multicastEvent方法时会激活监听器发布事件

public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
    ...
    Executor executor = this.getTaskExecutor();
    //获取bean容器注册的listeners
    Iterator var5 = this.getApplicationListeners(event, type).iterator();
    while(var5.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var5.next();
        if (executor != null) {
            executor.execute(() -> {
                //线程执行激活listener
                this.invokeListener(listener, event);
            });
        } else {
            this.invokeListener(listener, event);
        }
    }
}

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    // 监听器发布事件
    listener.onApplicationEvent(event);
    ...
}

registerListeners

通过ApplicationListenerDetector将实现ApplicationListener添加到广播器中等待发布

protected void registerListeners() {
    Iterator var1 = this.getApplicationListeners().iterator();
    //添加到广播器的内部类ListenerRetriever中集合中
    while(var1.hasNext()) {
        ApplicationListener<?> listener = (ApplicationListener)var1.next();
        this.getApplicationEventMulticaster().addApplicationListener(listener);
    }
    //getBeanNamesForType获取接口的所有实现bean
    String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
    String[] var7 = listenerBeanNames;
    int var3 = listenerBeanNames.length;

    for(int var4 = 0; var4 < var3; ++var4) {
        String listenerBeanName = var7[var4];
        //将实现beanName添加到ListenerRetriever
        this.getApplicationEventMulticaster()
            .addApplicationListenerBean(listenerBeanName);
    }
    //发布这个earlyEventsToProcess
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        Iterator var9 = earlyEventsToProcess.iterator();
        while(var9.hasNext()) {
            ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
            //multicastEvent发布事件的方法
            this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }

}

finishBeanFactoryInitialization

主要看其中的preInstantiateSingletons方法,这是IOC的核心,实例化所有的单例bean

这里会判断是factoryBean还是普通bean,因为实现 FactoryBean 接口,实现它的 getObject() 方法就可以自己定义创建实例对象的方法,比如很多中间件的实现

public void preInstantiateSingletons() throws BeansException {
    //所有的需要实例化的beanName都在beanDefinitionNames,包括 Aspectj的, 通过注解标识的
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    for (String beanName : beanNames) {
        //合并父类BeanDefinition
        //MergedBeanDefinition合并bean定义,XML 配置来注册 bean,会被封装成GenericBeanDefinition;使用注解的方式来注册 bean,会被封装成 ScannedGenericBeanDefinition,最终统一转换成 RootBeanDefinition处理
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        //非抽象,单例,非懒加载三个条件
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            //是 FactoryBean 类型的对象则加上&
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                ...
            }
            else {
                // 进入到doGetBean执行实例化bean
                getBean(beanName);
            }
        }
    }
}    

finishRefresh

bean的初始化已经全部完成,这一步主要是负责启动app和发布ContextRefreshedEvent事件

protected void finishRefresh() {
    //resourceCaches清除资源缓存
    this.clearResourceCaches();
    //初始化生命周期处理器负责管理ApplicationContext生命周期,默认使用DefaultLifecycleProcessor
    this.initLifecycleProcessor();
    //onRefresh启动容器生命周期,stop结束生命周期
    this.getLifecycleProcessor().onRefresh();
    //推送事件到相应监听器,监听器监听的就是事件
    //这里就是调用监听ContextRefreshedEvent事件的监听器的onApplicationEvent
    //比如监听自定义事件 MyListener implements ApplicationListener<MyEvent>
    //很重要的一点注意:发布事件的时候监听器才会去创建bean
    this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
    ...
}

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    ...
        //获取广播器发布事件
        this.getApplicationEventMulticaster()
        .multicastEvent((ApplicationEvent)applicationEvent, eventType);
}

public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
    //可以实现通过线程池执行任务
    Executor executor = this.getTaskExecutor();
    Iterator var5 = this.getApplicationListeners(event, type).iterator();
    while(var5.hasNext()) {
        //调用listener.onApplicationEvent(event),没有线程池则直接调用
        ApplicationListener<?> listener = (ApplicationListener)var5.next();
        if (executor != null) {
            executor.execute(() -> {
                this.invokeListener(listener, event);
            });
        } else {
            this.invokeListener(listener, event);
        }
    }
}

loadBeanDefinitions

loadBeanDefinitions有多个实现,这里以默认的XmlWebApplicationContext为例

通过解析器解析xml配置文件加载和注册bean,简单来说就是将Xml的配置全部解析出来封装成一个BeanDefinition交由BeanFactory管理

--XmlWebApplicationContext
// root context的默认配置位置
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
// 默认配置相对路径的前缀
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
// 默认配置位置的后缀
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";

//通过XmlBeanDefinitionReader加载bean
protected 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(getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   //空实现,留给XmlWebApplicationContext子类进行自定义初始化
   initBeanDefinitionReader(beanDefinitionReader);
   //使用给定的reader加载bean定义
   loadBeanDefinitions(beanDefinitionReader);
}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
    //就是context-param配置的contextConfigLocation,没有则返回context的默认配置
    //classpath*:appcontext-*.xml
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        for (String configLocation : configLocations) {
            //遍历xml配置文件进行加载解析DOM,最终注册到beanDefinitionMap
            reader.loadBeanDefinitions(configLocation);
        }
    }
}

进入loadBeanDefinitions,首先是要构建解析xml的解析器环境,将xml文件转为Resource并封装在InputSource中

--AbstractBeanDefinitionReader
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
    //解析bean配置文件加载器
    ResourceLoader resourceLoader = getResourceLoader();
    //XmlWebApplicationContext实现了ResourcePatternResolver接口
    //也就是以xml配置bean进行加载的,非xml配置就不会实现这个接口
    if (resourceLoader instanceof ResourcePatternResolver) {
        try {
            //将配置文件的内容转化为Resource对象
            //判断是否是classpath*:开头的通配符
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            //获取Resource对象流进行解析,转化为bean进行封装
            int loadCount = loadBeanDefinitions(resources);
    ...
}

//EncodedResource对Resource封装了字符集编码
public int loadBeanDefinitions(Resource resource) {
    //这里其实仅仅将resource封装了一层
    return loadBeanDefinitions(new EncodedResource(resource));
}

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    //使用ThreadLocal防止资源文件循环加载
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    //确认没有加载过当前的Resource
    if (currentResources == null) {
        currentResources = new HashSet<>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    try {
        //获取Resource的流
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            //InputSource可以简单理解为解析输入资源的所需条件的总装
            InputSource inputSource = new InputSource(inputStream);
            //这里encoding为null
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            //解析成DOM对象,进行Bean的加载和注册
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        ...
    }
}

registerBeanDefinitions

bean的加载和注册

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) {
    //解析xml封装为Document对象
    Document doc = doLoadDocument(inputSource, resource);
    //根据Document对象注册Bean
    return registerBeanDefinitions(doc, resource);
    ...
}    

BeanDefinition就是Bean的定义信息,封装了每个bean的信息,对于spring框架来说操作bean就是操作BeanDefinition;BeanFactory封装了所有注册的BeanDefinition(beanDefinitionMap)

refresh()-->obtainFreshBeanFactory()-->registerBeanDefinitions(),经过一系列的解析之后,最终将dom解析成BeanDefinition并封装到BeanFactory(DefaultListableBeanFactory)中

registerBeanDefinitions返回注册的Bean数量

---XmlBeanDefinitionReader
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   //构建读取Document的工具类
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   //BeanFactory实现BeanDefinitionRegistry接口
    //获取this.beanDefinitionMap.size()+
   int countBefore = getRegistry().getBeanDefinitionCount();
   //注册本次需要加载的Bean,createReaderContext构建一个XmlReaderContext
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   //返回本次注册的bean:总注册的bean减去之前注册的bean
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

---DefaultBeanDefinitionDocumentReader
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    this.doRegisterBeanDefinitions(doc.getDocumentElement());
}

protected void doRegisterBeanDefinitions(Element root) {
    //BeanDefinitionParserDelegate通过类名可知为解析代理
    //封装了bean相关的Xml属性
    BeanDefinitionParserDelegate parent = this.delegate;
    //创建bean解析代理
    this.delegate = createDelegate(getReaderContext(), root, parent);
    //是否匹配:"http://www.springframework.org/schema/beans"
    if (this.delegate.isDefaultNamespace(root)) {
        //profile:根节点属性,是否匹配当前环境,不匹配则不解析当前xml文件
        //<beans xmlns="http://www.springframework.org/schema/beans" profile="test"...>
        String profileSpec = root.getAttribute("profile");
        ...
    }
    //解析root节点之前的操作,空实现,留给子类实现
    preProcessXml(root);
    //解析dom的root节点判断命名空间是否为默认的
    //默认命名http://www.springframework.org/schema/beans
    parseBeanDefinitions(root, this.delegate);
    //解析root节点之后的操作,空实现
    postProcessXml(root);
    //通过这个方式还原初始化的BeanDefinitionParserDelegate
    this.delegate = parent;
}

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    //有默认的namespace
   if (delegate.isDefaultNamespace(root)) {
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         if (node instanceof Element) {
            Element ele = (Element) node;
            if (delegate.isDefaultNamespace(ele)) {
               // 解析 default namespace 下面的几个四个元素
               //<import/>、<alias/>、<bean/> 和 <beans/>
               parseDefaultElement(ele, delegate);
            }
            else {
               // 解析其他 namespace 的元素
               //例如:<context:component-scan/>、<aop:aspectj-autoproxy/>
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
   // 解析自定义 namespace 的元素
      delegate.parseCustomElement(root);
   }
}

createReaderContext

构建一个解析容器XmlReaderContext,XmlReaderContext继承的ReaderContext封装了透传的Resource和eventListener,而其封装了XmlBeanDefinitionReader(当前bean解析器)和NamespaceHandlerResolver(也是当前解析器封装的透传给容器的)

---XmlBeanDefinitionReader
public XmlReaderContext createReaderContext(Resource resource) {
    return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.getNamespaceHandlerResolver());
}

public class XmlReaderContext extends ReaderContext {
    private final XmlBeanDefinitionReader reader;
    private final NamespaceHandlerResolver namespaceHandlerResolver;
    //problemReporter,eventListener和sourceExtractor都是透传的空实现
    //resource是加载xml的资源,reader是透传自己
    public XmlReaderContext(Resource resource, ProblemReporter problemReporter, ReaderEventListener eventListener, SourceExtractor sourceExtractor, XmlBeanDefinitionReader reader, NamespaceHandlerResolver namespaceHandlerResolver) {
        super(resource, problemReporter, eventListener, sourceExtractor);
        this.reader = reader;
        //默认的 handlerMappingsLocation = "META-INF/spring.handlers";
        //作用就是获取xsd对应的处理器
        this.namespaceHandlerResolver = namespaceHandlerResolver;
    }
}

namespaceHandlerResolver: 默认值为META-INF/spring.handlers获取该配置项所有的handler类,实现了NamespaceHandler并封装在handlerMappings中;当然也可以自定义一些handler并配置在默认的目录下,这些handler实现parse和decorate方法

image

createDelegate

初始化解析代理,delegate封装了readerContext,DocumentDefaultsDefinition等

---DefaultBeanDefinitionDocumentReader
protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, @Nullable BeanDefinitionParserDelegate parentDelegate) {
    //BeanDefinitionParserDelegate设值readerContext
    BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
    //初始化delegate
    delegate.initDefaults(root, parentDelegate);
    return delegate;
}

public void initDefaults(Element root, @Nullable BeanDefinitionParserDelegate parent) {
    //defaults:DocumentDefaultsDefinition
    this.populateDefaults(this.defaults, parent != null ? parent.defaults : null, root);
    //可自定义实现EventListener(这里ReaderEventListener是个空实现)
    this.readerContext.fireDefaultsRegistered(this.defaults);
}

populateDefaults会处理beans标签的属性(默认解析的方法),解析的属性值都被封装在defaults,也就是DocumentDefaultsDefinition中

//bean标签一般也会指定lazy-init/init-method等方法,也可以在beans指定默认方法
<beans ...
     default-lazy-init="true" default-init-method="">

parseDefaultElement

解析默认namespace,默认的命名空间beans只包含了import、alias、bean 和 beans四个标签,其中beans又是一个嵌套的dom继续递归调doRegisterBeanDefinitions

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    // import标签:解耦式的导入,将其他xml配置文件引入解析
    //比如<import resource="classpath:app.xml" />
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    // alias标签:<alias name="test" alias="test1,test2"/>
    //作用就是增加test1,test2作为bean名称指向bean
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    //解析bean标签,并注册beanDefinition
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    //beans标签:递归方法解析
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        doRegisterBeanDefinitions(ele);
    }
}

processBeanDefinition核心在于解析bean标签并注册beanDefinition到factory

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //解析之后BeanDefinition,beanName以及aliases封装到BeanDefinitionHolder
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        //当对默认namespace的xsd增加了自定义子标签时去通过handler解析
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        //执行注册,将BeanDefinition信息添加到beanFactory中
        BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        //自定义实现ReaderEventListener的componentRegistered方法
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

将beanDefinition、beanName、bean别名数组封装成BeanDefinitionHolder

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    //解析bean的属性,id,name和<alias>配置的别名都可以作为bean的key值
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // 获取name属性,缓存至别名List
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    List<String> aliases = new ArrayList<>();
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }
    // 如果bean的id为空,但是别名不为空的话,那么默认采用第一个别名作为beanName
    // 例如:<bean class="com.xx.Dog" name="myDog1,myDog2"/>
    String beanName = id;
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        //使用myDog1作为beanName,并移除别名集合
        beanName = aliases.remove(0);
    }
    //检查beanName和别名是否被使用
    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }
    //重载方法,解析bean标签,将属性及子节点信息封装
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    ....
}

解析bean及子节点标签封装到BeanDefinition

public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    //this.beanDefinitionName = beanName
    this.parseState.push(new BeanEntry(beanName));
    //解析class属性,类全限定名
    String className = null;
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }
    //解析parent属性
    String parent = null;
    if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
        parent = ele.getAttribute(PARENT_ATTRIBUTE);
    }
    //创建AbstractBeanDefinition对象,将标签的信息进行封装
    AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    //解析bean标签属性
    parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    //解析bean标签下的子节点并封装到bd中
    //包括<property/>,<constructor-arg />注入之类标签等等
    bd.set....
}

parseBeanDefinitionAttributes解析bean属性封装到BeanDefinition

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,BeanDefinition containingBean,AbstractBeanDefinition bd) {
    // 1.设置bean作用域scope属性,不能设置为单例
    // 未明确指定bean的作用域,且当前被解析bean是内部bean的话,
    // 则默认使用outer bean的的作用域作为当前bean的作用域
    // 例如:下面的配置,解析到inner属性时,inner未指定作用域,则使用outer的作用域,也就是prototype
    /**
        <bean id="outer" class="com.lyc.cn.v2.day01.inner.Outer" scope="prototype">
            <property name="inner">
                <bean id="inner" class="com.lyc.cn.v2.day01.inner.Inner"/>
            </property>
         </bean>
     **/
     bd.setScope(containingBean.getScope());
    //2.设置abstract属性:abstract=true
    // 3.设置lazy-init(延迟加载)属性;
    // 如果该属性为true的话,ApplicationContext容器在初始化时不会加载该bean;
    // 而是在第一次向容器索取该bean时才会被初始化
    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
    //4.设置autowire属性,自动注入,有byName和byType方式,默认不开启
    //byName,按照setXxx方法的Xxx名称去注入bean
    //byTupe,按照set方法的入参属性类去注入bean
    bd.setAutowireMode(getAutowireMode(autowire));
    //5.设置depends-on属性,如果BeanA依赖于BeanB,可通过depends-on属性使BeanB在BeanA之前完初始化
    //6.设置autowire-candidate属性,默认为true
    //当设置为false时,不让其他类通过autowire注入当前bean
    // 7、设置primary属性,当byType注入有多个类型时,
    // 可以指定primary="true",提高注入的优先级,避免抛出异常
    // 8、设置init-method,bean初始化完成后回调该方法
    // 9、设置destroy-method属性,bean销毁后回调该方法
    // 10、设置factory-method属性,该属性可指定静态工厂或实例工厂方法实例化bean
    // 11、设置factory-bean属性,一般和factory-method属性一起使用,
    // 指定工厂bean和工厂bean的工厂方法
}

BeanDefinitionReaderUtils.registerBeanDefinition去执行注册

---BeanDefinitionReaderUtils
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
    //注册beanName与beanDefinition的映射
    String beanName = definitionHolder.getBeanName();
    //由registry的子类DefaultListableBeanFactory实现
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            //由SimpleAliasRegistry实现,是当前BeanFactory的父类
            //主要作用是将去重(不能和beanName相同)的别名和beanName形成映射
            //aliasMap:key为别名,value为beanName
            registry.registerAlias(beanName, alias);
        }
    }
}

注册bean,将beanName和BeanDefinition形成映射,将beanName添加到各个相应的集合中

---DefaultListableBeanFactory
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
    if (beanDefinition instanceof AbstractBeanDefinition) {
        //验证不能有静态工厂方法(factory-method的配置)
        ((AbstractBeanDefinition) beanDefinition).validate();
    }
    //优先从缓存中加载BeanDefinition,覆盖原先的bean
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
        //添加到beanfactory的beanDefinitionMap中
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }else {
        // 如果beanDefinition已经被标记为创建(为了解决单例bean的循环依赖问题)
        //alreadyCreated为空
        if (hasBeanCreationStarted()) {
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                //更新updatedDefinitions的容量,并添加重新添加所有beanName
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                // 将updatedDefinitions赋值给beanDefinitionNames
                this.beanDefinitionNames = updatedDefinitions;
                // 手动单例集合manualSingletonNames,bean已存在则移除
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        }else {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            // manualSingletonNames缓存的是手动注册的单例bean
            // 例如:xmlBeanFactory.registerSingleton("myDog", new Dog());
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
    // 如果当前注册的bean的定义已经在beanDefinitionMap缓存中存在,
    // 或者实例已经存在于单例bean的缓存中,将该beanName对应的缓存信息、单例对象清除
    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

parseCustomElement

解析其他namespace

xmlns 属性可以在文档中定义一个或多个可供选择的命名空间,使用时在子标签内添加他的前缀作为标识: 比如context,aop等

<beans xmlns="http://www.springframework.org/schema/beans" profile="test"
   xmlns:context="http://www.springframework.org/schema/context"...  
----context:----作为另外的一个命名空间标识
  <context:component-scan base-package="cn.mytest.spring" />

delegate.parseCustomElement解析非默认标签和自定义namespace

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    // node.getNamespaceURI拿到节点的命名空间,例如常见的:
    // <aop> 节点对应命名空间: http://www.springframework.org/schema/aop
    String namespaceUri = getNamespaceURI(ele);
    // 命名空间对应的的handler, 例如:contex 对应 ContextNameSpaceHandler
    //namespaceHandlerResolver解析namespaceUri, 拿到NamespaceHandler
    NamespaceHandler handler = this.readerContext
        .getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
        return null;
    }
    // handler解析节点(ParserContext用于存放解析需要的一些上下文信息)
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

readerContext.getNamespaceHandlerResolver()获取了默认的命名空间处理器DefaultNamespaceHandlerResolver,其封装了所有包下的handler

每个包下MATA-INF/spring.handlers文件记录对应的hanlder,因此使用指定的 classLoader 从所有类路径资源(META-INF/spring.handlers)加载所有属性,并使用 Properties 来存放 spring.handlers 文件中的内容(命名空间和 handler 的键值对)

--MATA-INF/spring.handler
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler"

//使用给定的类加载器从指定的类路径资源加载所有属性
Properties mappings = PropertiesLoaderUtils
.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
//将Properties转换成Map, mappings -> handlerMappings
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);

每个命名空间处理都会封装不同标签的bean解析器,例如ContextNamespaceHandler中封装了诸如property-placeholder,annotation-config等标签解析器

    <!-- 加载db.properties文件,属性占位 -->
    <context:property-placeholder location="classpath:db.properties"
        system-properties-mode="NEVER" />

    <!-- DI的解析器 -->
    <context:annotation-config />
    <!-- IoC的解析器 -->
    <context:component-scan base-package="cn.wolfcode.wms" />

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
   @Override
   public void init() {
      registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
      registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
      registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
      registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
      registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
      registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
   }
}

先获取每个标签对应的BeanDefinitionParser解析器,再根据不同的解析器去实现parse方法,对于各个标签的解析功能暂不深入,主要是太多了,也可以自定义namespace和标签

private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    //拿到节点的localName,例如:<context:annotation-config />
    String localName = parserContext.getDelegate().getLocalName(element);
    //从parsers缓存中,拿到localName对应的解析器, 例如: component-scan -> ComponentScanBeanDefinitionParser
    BeanDefinitionParser parser = this.parsers.get(localName);
    return parser;
}

--parser.parse(element, parserContext);

BeanPostProcessor

Bean的后置处理器,其作用或者说触发条件是在构建bean之后,并且在init()之前和之后对所有的bean进行切面的增强;实现方式一般是先实现BeanPostProcessor,然后判断是否是xxxAware接口的实现类,从而对这些bean增强

public interface BeanPostProcessor {
    //在init方法之前执行
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    //在init方法之后执行
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

ApplicationContextAwareProcessor

对实现ApplicationContextAware的bean注入一个applicationContext,这个处理器比较简单

---ApplicationContextAwareProcessor
//对实现了ApplicationContextAware接口的bean填充一个ApplicationContext
if (bean instanceof ApplicationContextAware) {
 ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}

//实现ApplicationContextAware可以获取到applicationContext
//一般用于不方便直接去注入applicationContext时用
@Component
public class SpringBootApolloRefreshConfig implements ApplicationContextAware {
    private ApplicationContext applicationContext;
        @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

ApplicationListenerDetector

将实现ApplicationListener的bean添加到beanFactory的applicationListeners中

---ApplicationListenerDetector
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean instanceof ApplicationListener) {
        Boolean flag = (Boolean)this.singletonNames.get(beanName);
        if (Boolean.TRUE.equals(flag)) {
            this.applicationContext.addApplicationListener((ApplicationListener)bean);
        }
    }
    return bean;
}

LoadTimeWeaverAwareProcessor

当开启LTW时会添加这个处理器,从织入切面的方式上来看,存在三种织入方式:编译期织入、类加载期织入和运行期织入:

  • 1.运行期织入
    这是最常见的,比如在运行期通过为目标类生成动态代理的方式实现AOP就属于运行期织入,这也是Spring AOP中的默认实现,并且提供了两种创建动态代理的方式:JDK自带的针对接口的动态代理和使用CGLib动态创建子类的方式创建动态代理。
  • 2.编译期织入
    使用特殊的编译器在编译期将切面织入目标类,这种比较少见,因为需要特殊的编译器的支持。
  • 3.类加载期织入
    通过字节码编辑技术在类加载期将切面织入目标类中,在目标类的class文件被JVM加载前,通过自定义类加载器或者类文件转换器将横切逻辑织入到目标类的class文件中,然后将修改后class文件交给JVM加载,这种织入方式称为LTW(LoadTimeWeaving)。

spring开启 loadtimeweaver, 有三个选项 : on, off, auto-detect;如果设置为 auto-detect, spring 将会在 classpath 中查找aspejct 需要的 META-INF/aop.xml, 如果找到则开启 aspectj weaving

<context:load-time-weaver aspectj-weaving="autodetect" />
或者
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.AUTODETECT)
@EnableAspectJAutoProxy

LoadTimeWeaverAwareProcessor将beanFactory中已存在的LoadTimeWeaver设值到AspectJWeavingEnabler(实现LoadTimeWeaverAware接口)

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof LoadTimeWeaverAware) {
         LoadTimeWeaver ltw = (LoadTimeWeaver)this.beanFactory.getBean("loadTimeWeaver", LoadTimeWeaver.class);
        ((LoadTimeWeaverAware)bean).setLoadTimeWeaver(ltw);
    }
    return bean;
}

doGetBean

refresh执行到finishBeanFactoryInitialization时才开始初始化非延迟加载的bean,通过不断的加载配置文件和资源文件,不断的封装缓存和需要处理的内容,最后进行类加载处理,进行封装和处理

protected <T> T doGetBean(String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly) throws BeansException {
    //去掉FactoryBean的前缀“&”,解析别名返回namespace的beanName
    String beanName = this.transformedBeanName(name);
    //实现三级缓存获取bean实例,不涉及创建新的bean实例
    Object sharedInstance = this.getSingleton(beanName);
    Object bean;
    //缓存中如果能获取到
    if (sharedInstance != null && args == null) {
        //普通bean直接返回实例,factoryBean继续处理
        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
    } else {
        //和singletonsCurrentlyInCreation类似存放正在创建的Prototype实例
        //循环依赖校验:当前原型实例池中有正在创建的对象了,说明这个对象是个原型对象,并且当前线程中这个对象已经处于创建中了,会造成循环依赖
        if (this.isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }   
        BeanFactory parentBeanFactory = this.getParentBeanFactory();
        //当前BeanFactory中的beanDefinitionMap找不到当前Bean,则从parentBeanFactory获取
        if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
            //解析别名和去掉FactoryBean的前缀
            String nameToLookup = this.originalBeanName(name);
            //使用父类的doGetBean方法实例化bean
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }
            ...
        }
        //继续往下,类型检测默认为false,将beanName添加到alreadyCreated缓存
        if (!typeCheckOnly) {
            this.markBeanAsCreated(beanName);
        }
        //RootBeanDefinition可以理解为一个没有parent的独立BeanDefinition
        //Map<String, RootBeanDefinition> mergedBeanDefinitions
        //如果mergedBeanDefinitions没有父类定义就是BeanDefinition本身
        RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
        //检查是抽象类则抛异常
        this.checkMergedBeanDefinition(mbd, beanName, args);
        //获取所有当前bean的依赖,需要在依赖创建之后才能进行实例创建
        //@DependsOn这个熟悉的注解:需要依赖另一个bean的实例创建
        String[] dependsOn = mbd.getDependsOn();
        if (dependsOn != null) {
            for (String dep : dependsOn) {
                // 检查是否依赖于beanName,即存在循环依赖
                if (isDependent(beanName, dep)) {
                    throw new BeanCreationException();
                }
                //将dep和beanName的依赖关系注册到dependentBeanMap中
                registerDependentBean(dep, beanName);
                //先实例化依赖的Bean
                getBean(dep);
            }
            //实例化不同的scope域的Bean
            if (mbd.isSingleton()) {
                //重载方法
                //getSingleton(String beanName, ObjectFactory<?> singletonFactory)
                sharedInstance = this.getSingleton(beanName, () -> {
                    //singletonFactory.getObject()方法最终执行的是createBean()方法
                    try {
                        return this.createBean(beanName, mbd, args);
                    } catch (BeansException var5) {
                        this.destroySingleton(beanName);
                        throw var5;
                    }
                });
                //跟上面一样返回普通的实例对象
                bean = this.getObjectForBeanInstance(sharedInstance,name,beanName, mbd);
            } else if (mbd.isPrototype()) {
                //scope为prototype的bean创建
                var11 = null;
                Object prototypeInstance;
                try {
                    //添加到缓存prototypesCurrentlyInCreation中
                    this.beforePrototypeCreation(beanName);
                    //创建实例
                    prototypeInstance = this.createBean(beanName, mbd, args);
                } finally {
                    //移除prototypesCurrentlyInCreation中的缓存
                    this.afterPrototypeCreation(beanName);
                }
                //普通Bean直接返回
                bean=this.getObjectForBeanInstance(prototypeInstance,name,beanName, mbd);
            } else {
                //其他scope的bean创建
                String scopeName = mbd.getScope();
                Scope scope = (Scope)this.scopes.get(scopeName);
                //实现的也是ObjectFactory
                Object scopedInstance = scope.get(beanName, () -> {
                    //通过getObject方法调用,和prototype创建bean实例一致
                    this.beforePrototypeCreation(beanName);
                    Object var4;
                    try {
                        var4 = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }
                    return var4;
                });
                bean=this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
        }
    }
}...

getSingleton

spring通过三级缓存方式解决循环依赖:

Spring 能解决的循环依赖有:通过 setter 注入的循环依赖、通过属性注入的循环依赖,当构造器出现循环依赖则无法解决,所以需要先用构造函数创建一个 “不完整” 的 bean 实例

//singletonObjects 一级缓存:实例化保存的单例 bean 对象
private final Map<String, Object> singletonObjects;
//earlySingletonObjects 二级缓存:还未进行属性填充、初始化 
private final Map<String, Object> earlySingletonObjects;
//singletonFactories 三级缓存:存放BeanName与bean工厂
private final Map<String, ObjectFactory<?>> singletonFactories;
//在Bean开始实例化时将bean存放,创建完成时会将其移出
private final Set<String> singletonsCurrentlyInCreation;
//Bean被创建完成后添加
private final Set<String> alreadyCreated;
//已经注册的单例bean,三级缓存中任意添加了都会同步添加到这里
private final Set<String> registeredSingletons

getSingleton重载方法每次都会先去从缓存中获取,分别尝试从一级,二级,三级缓存中获取BeanName对应的bean,如果三级缓存中有,则将三级缓存中的对象放到二级缓存中,清除三级缓存。如果没有获取到,则创建以后会放到一级缓存中,同时清空二三级缓存

image

getSingleton有多个重载的方法

---DefaultSingletonBeanRegistry
//allowEarlyReference表示是否允许从singletonFactories中通过getObject拿到对象
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //从一级缓存中获取
    Object singletonObject = this.singletonObjects.get(beanName);
    //isSingletonCurrentlyInCreation表示正在进行创建中,从二级缓存中获取
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        Map var4 = this.singletonObjects;
        synchronized(this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            //允许三级缓存,通过getObject()获取
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    //获取到了则添加到二级缓存中,并移除三级缓存的对象
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    //这个getSingleton方法的重载就是从缓存获取bean实例,没有去创建新的实例
    return singletonObject;
}

重载方法的参数singletonFactory 通过 getObject 方法创建bean 实例

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Map var3 = this.singletonObjects;
    synchronized(this.singletonObjects) {
        //还是先从缓存中拿
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            //表示正在创建Bean状态
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException();
            }
            //将beanName加入到正在创建bean的缓存singletonsCurrentlyInCreation中
            this.beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            try {
                //执行creatBean()方法
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            } finally {
                //从singletonsCurrentlyInCreation移除beanName
                this.afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                /**创建新的Bean成功添加到一级缓存中,并移除二三级缓存
                    this.singletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                    this.earlySingletonObjects.remove(beanName);
                    this.registeredSingletons.add(beanName);
                **/
                this.addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

createBean

singleton实例由实现ObjectFactory接口的getObject方法中去createBean()实现,而prototype实例则直接调用默认的createBean(),还是Spring传统最终由doCreateBean实现

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    //bean包装类
    BeanWrapper instanceWrapper = null;
    if (instanceWrapper == null) {
        //创建Bean实例,调用构造方法实例化对象,理解为new一个
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }
    //获取原始对象和其类型
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }
    //bean预处理器,bean处理器增强bean
    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    //满足单例,允许循环依赖,正在实例创建中三个条件:添加ObjectFactory到singletonFactories
    boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    if (earlySingletonExposure) {
        this.addSingletonFactory(beanName, () -> {
            //可以实现AOP的逻辑
            return this.getEarlyBeanReference(beanName, mbd, bean);
        });
    }
    Object exposedObject = bean;
    //bean的属性的填充,也存在对象字段和Autowired注入的字段,所以还是一样去递归初始化依赖的bean
    //和@Depend-on不同,dependOn更多的目的是实例创建的顺序控制
    //循环依赖的处理,后置处理器解析@Autowired等进行属性填充
    this.populateBean(beanName, mbd, instanceWrapper);
    //bean增强,@PostConstruct>InitializingBean>init()
    exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    //允许循环依赖进行见检查
    if (earlySingletonExposure) {
        Object earlySingletonReference = this.getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            //initializeBean没有处理exposedObject则将缓存的bean暴露
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
                //initializeBean处理之后会产生一个代理对象且有被依赖的bean
            } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                //将这些依赖exposedObject的bean数组移除,因为Bean已经不是原来的bean了
                String[] dependentBeans = this.getDependentBeans(beanName);
                ...
}

registerDependentBean

创建bean实例之前需要将相互依赖关系进行维护

//用于保存bean在singletonObjects中的key名称到bean的名称集合的映射
Map<String, Set<String>> containedBeanMap;
//dependentBeanMap存放当前bean依赖的,key就是当前beanName,value就是已经注册的bean集合,value简单理解就是注入到的当前实例bean的集合
Map<String, Set<String>> dependentBeanMap;
//dependenciesForBeanMap存放的是依赖当前bean的实例集合
Map<String, Set<String>> dependenciesForBeanMap;

---DefaultSingletonBeanRegistry
public void registerDependentBean(String beanName, String dependentBeanName) {
    String canonicalName = this.canonicalName(beanName);
    Map var4 = this.dependentBeanMap;
    Set dependenciesForBean;
    synchronized(this.dependentBeanMap) {
        //java8新方法computeIfAbsent方法用来计算给定key,返回value映射值。如果,key前并没有映射到一个值,或者映射到null,那么,就用计算出来的值放到这个hashmap中
        //获取自己依赖的bean集合将dependentBeanName添加进去
        dependenciesForBean = (Set)this.dependentBeanMap
            .computeIfAbsent(canonicalName, (k) -> {
                return new LinkedHashSet(8);
        });
        if (!dependenciesForBean.add(dependentBeanName)) {
            return;
        }
    }
    var4 = this.dependenciesForBeanMap;
    synchronized(this.dependenciesForBeanMap) {
        //自己依赖dependentBeanName,所以需要将自己添加到dependenciesForBeanMap的value中
        dependenciesForBean = (Set)this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, (k) -> {
            return new LinkedHashSet(8);
        });
        dependenciesForBean.add(canonicalName);
    }
}

自定义事件/监听器

监听器在事件发布的时候才会创建Bean,也只有在事件发布的时候才能执行监听器的onApplicationEvent方法

自定义一个事件,如果ApplicationListener<MyEvent>不加泛型会默认监听ApplicationEvent和其子类事件,而容器启动的时候,执行finishRefresh方法发布ContextRefreshedEvent事件

//自定义事件
public class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
    }
}

多种容器使用自定义事件和监听器

--- spring方式
//发布自定的事件
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
context.publishEvent(new MyEvent("11111")); //myListener:com.pingan.mytest.listener.MyEvent[source=11111]

//如果只想监听自定义的事件则补充好泛型
//@Component标记
@Component
public class MyListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent myEvent) {
        System.out.println("myListener:"+myEvent.toString());
    }
}
--- springboot方式
@SpringBootApplication
public class SingleManApp {
    //通过添加自定义的addApplicationListener和发布自定义事件
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(SingleManApp.class);
        //如果MyListener被@Component标记则不需要再添加这个
        run.addApplicationListener(new MyListener());
        run.publishEvent(new MyEvent("1111"));
    }
}

@SpringBootApplication
public class SingleManApp {
    //SpringApplication不能发布事件,但是可以添加监听器
    public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(SingleManApp.class);
        //这里是添加到SpringApplication容器的监听器
        //可以只需要对自定义的监听器加@Component标记即可
        springApplication.addListeners(new MyListener());
        springApplication.run(args);
    }
}

相关文章

网友评论

      本文标题:深度解析Spring源码

      本文链接:https://www.haomeiwen.com/subject/mwdonktx.html