IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring ioc容器初始化(一) -> 正文阅读

[Java知识库]Spring ioc容器初始化(一)

一、ApplicationContext

ApplicationContext是spring继BeanFactory之外的另一个核心接口或容器,允许容器通过应用程序上下文环境创建、获取、管理bean。

在Spring 中, BeanFactory 接口的各种实现负责bean实例化,为Spring 管理的bean提供依赖注入和生命周期支持。然而,作为BeanFactory接口的扩展, ApplicationContext 还提供其他有用的功能。ApplicationContext 的主要功能是提供一个更丰富的框架来构建应用程序。ApplicationContext 更加了解所配置的bean(与BeanFactory 相比), 在使用Spring 基础结构类和接口(例BeanFactoryPostProcessor) 的情况下,ApplicationContext 可以代替你与这些类或接口进行交互, 从而减少为了使用Spring 所需编写的代码量。

使用ApplicationContext 的最大好处是,它允许以完全声明的方式配置和管理Spring 以及Spring 所管理的资源。这意味着Spring 尽可能提供支持类来自动将ApplicationContext 加载到应用程序中,从而不需要编写任何代码来访问ApplicationContext。

二:常见的ApplicationContext

spring为ApplicationContext提供了很多实现类,其中有四个比较常用的:
ClassPathXmlApplicationContext
通过读取工程src目录下的配置文件启动ioc容器

ApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml ");

FileSystemXmlApplicationContext
通过读取系统文件路径下的配置文件启动ioc容器

ApplicationContext context = new FileSystemXmlApplicationContext( "D:/test/applicationContext.xml ");

AnnotationConfigWebApplicationConetxt
通过配置类的方式启动ioc容器

uml如图:
请添加图片描述
三、ioc容器的初始化
可以看到以上ApplicationContex都有个父类是AbstractApplicationContext,refresh()方法是该父类的方法,在ioc容器的启动过程中都会走调用refresh()方法,refresh 函数中包含了几乎ApplicationContext 中提供的全部功能,而且此函数中逻辑非常清晰明了, 使我们很容易分析对应的层次及逻辑:

public void refresh() throws BeansException , IllegalStateException {
    synchronized (this. startupShutdownMonitor) {
        //准备刷新的上下文环境
        prepareRefresh() ;
        
        //初始化BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() ;
        
        //对BeanFactory 进行各种功能填充
        prepareBeanFactory(beanFactory) ;
        try {
        
            //子类覆盖方法做额外的处理
            postProcessBeanFactory(beanFactory) ;
            //激活各种BeanFactory 处理器
            invokeBeanFactoryPostProcessors(beanFactory) ;
            //注册拦截Bean 后置处理器, 这里只是注册,真正的调用是在getBean的时候
            registerBeanPostProcessors(beanFactory);
            //为上下文初始化Message 源, 即不同语言的消息体, 国际化处理
            initMessageSource();
            
            //初始化应用消息广播器, 并放入applicationEventMulticaster中
            initApplicationEventMulticaster();
            
            //留给子类来初始化其它的Bean
            onRefresh();
            
            //在所有注册的bean中查找Listenerbean ,注册到消息广播中
            registerListeners();
            
            //初始化剩下的单实例(非惰性的)
            finishBeanFactoryinitialization(beanFactory);
            
            //完成refresh,同时发出ContextRefreshEvent 通知别人
            finishRefresh() ;
        catch (BeansException ex) {
            destroyBeans();
            cancelRefresh(ex) ,
            throw ex;
    }
}

1、AbstractApplicationContext#prepareRefresh()

protected void prepareRefresh() {
   // Switch to active. 记录上下文的启动时间
   this.startupDate = System.currentTimeMillis(); 
    //上下文是否关闭标志
   this.closed.set(false);
    //上下文是否活跃标志
   this.active.set(true);
   if (logger.isDebugEnabled()) {
      if (logger.isTraceEnabled()) {
         logger.trace("Refreshing " + this);
      }
      else {
         logger.debug("Refreshing " + getDisplayName());
      }
   }
 
//空方法,未做任何处理,正符合Spring 的开放式结构设计,给用户最大扩展Spring 的能力。
//用户可以根据自身的需要重写initPropertySources方法,并在方法中进行个性化的属性处理及设置
   initPropertySources();
   getEnvironment().validateRequiredProperties();
    //earlyApplicationListeners是刷新之前就会注册的本地监听器Set集合,applicationListeners是静态指定的监听器Set集合,
    //当earlyApplicationListeners为空时,会初始化内容是applicationListeners;当earlyApplicationListeners不为空时,
    //会将applicationListeners清空,内容再重置为earlyApplicationListeners。
   if (this.earlyApplicationListeners == null) {
      this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
   }
   else {
      
      this.applicationListeners.clear();
      this.applicationListeners.addAll(this.earlyApplicationListeners);
   }
    //初始化earlyApplicationEvents属性,earlyApplicationEvents是在多播器设置之前发布的应用程序事件。
   this.earlyApplicationEvents = new LinkedHashSet<>();

2、AbstractApplicationContext#obtainFreshBeanFactory()

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
     refreshBeanFactory();
     return getBeanFactory();
}
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 是否已经存在了BeanFactory
   if (hasBeanFactory()) {
         // 销毁beans
         destroyBeans();
         // 关闭已存在的BeanFactory
         closeBeanFactory();
   }
   try {
      // 创建新的BeanFactory对象 -> DefaultListableBeanFactory
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      //为了序列化指定id,如果需要的话, 让这个BeanFactory 从id反序列化到BeanFactory 对象
      beanFactory.setSerializationId(getId());
   
      //定制beanFactory , 设置相关属性, 包括是否允许覆盖同名称的不同定义的对象以及循环付己赖以及
      //设置@Autowired 和自Qualifier 注解解析器QualifierAnnotationAutowireCandidateResolver
      // 该方法主要对2个标志进行设置:allowBeanDefinitionOverriding和allowCircularReferences
      // allowBeanDefinitionOverriding:是否允许使用相同名称重新注册不同的bean(Spring默认true,SpringBoot默认false)
      // allowCircularReferences:是否允许循环依赖(默认为true)
      customizeBeanFactory(beanFactory);
     
       //初始化DodumentReader,并进行XML文件读取及解析
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

DefaultListableBeanFactory
BeanFactory创建方式为:

BeanFactory bf= new XmlBeanFactory("beanFactoryTest.xml")

其中的XmlBeanFactory 继承自DefaultListableBeanFactory,并提供了XmlBeanDefinitionReader 类型的reader 属性, 也就是说DefaultListableBeanFactory是容器的基础。必须首先要实例化,那么在这里就是实例化DefaultListableBeanFactory的步骤。

2.1、destroyBeans()

// 当前这个单例是否在销毁,true=已执行destory方法,或者出现异常时执行了destroySingleton方法
private boolean singletonsCurrentlyInDestruction = false;
// 缓存Bean与Bean的包含关系
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<String, Set<String>>(16);
// 缓存Bean与其它依赖Bean的关系
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64);
// 缓存被依赖Bean与其它依赖Bean的关系
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64);
public void destroySingletons() {
    if (logger.isDebugEnabled()) {
        logger.debug("Destroying singletons in " + this);
    }
    synchronized (this.singletonObjects) {
        // 设置清理标识
        this.singletonsCurrentlyInDestruction = true;
    }
    // 销毁disposableBeans缓存中所有单例bean
    String[] disposableBeanNames;
    synchronized (this.disposableBeans) {
        disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
    }
    for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
        destroySingleton(disposableBeanNames[i]);
    }
    // 清空包含关系
    this.containedBeanMap.clear();
    // 清空依赖和被依赖关系
    this.dependentBeanMap.clear();
    this.dependenciesForBeanMap.clear();
    // 清空缓存
    clearSingletonCache();
}

可以看到destroy其实就是去清空容器中的缓存。

2.2、customizeBeanFactory 定制beanFactory

这里已经开始了对BeanFactory 的扩展,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置并提供了注解@Qualifier 和@Autowired 的支持。

protected void customizeBeanFactory (DefaultListableBeanFactory beanFactory ) {
    //如果属性allowBeanDefinitionOverroding 不为空,设置给beanFactory 对象相应属性,
    //此属性的含义,是否允许覆盖同名称的不同定义的对象
    if (this.allowBeanDefinitionOverriding 1= null ) {
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding) ;
    }
    //如果属性allowCircularReferences 不为空,设置给beanFactory对象相应属性,
    //此属性的含义,是否允许bean之间存在循环依赖
    if (this.allowCircularReferences != null ) {
         beanFactory.setAllowCircularReferences(this.allowCircularReferences );
        //用于自Qualifier 和l @Autowired
        beanFactory .setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver()); 
 }

敲重点:是否允许bean的循环依赖配置在这里。
allowBeanDefinitionOverroding的配置可以覆盖相同名称的bean,这个配置要慎重开启。

3、prepareBeanFactory(beanFactory)

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // 设置beanFactory的类加载器为当前类加载器.
   beanFactory.setBeanClassLoader(getClassLoader());
   // 通过在 spring.properties 配置是否开启 表达式语言解析器,默认是(不忽略)
   if (!shouldIgnoreSpel) {
      beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   }
   //为beanFactory 增加了一个默认的propertyEditor ,这个主要是对bean 的属性等设置管理的一个工具
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
   /*
    *ApplicationContextAwareProcessor是一个Spring内部工具,它实现了接口BeanPostProcessor,
    * 用于向实现了如下某种Aware接口的bean设置ApplicationContext中相应的属性:
      EnvironmentAware
      EmbeddedValueResolverAware
      ResourceLoaderAware
      ApplicationEventPublisherAware
      MessageSourceAware
      ApplicationContextAware
    */
   // 添加前置处理器.
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   //设置忽略装配
   /*ignoredDependencyInterface方法并不是让我们在自动装配时直接忽略实现了该接口的依赖。
    * 这个方法的真正意思是忽略该接口的实现类中和接口setter方法入参类型相同的依赖。
    */
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
   /*
      在Spring自动装配的时候如果一个接口有多个实现类,并且都已经放到IOC中去了,
      那么自动装配的时候就会出异常,因为spring不知道把哪个实现类注入进去,
      但是如果我们自定义一个类,然后实现BeanFactoryPostProcessor接口
      在该阶段调用这个方法,如果哪个地方要自动注入这个类型的对象的话,那么就注入进去我们指定的对象
    */
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);
   // 在Bean初始化后检查是否实现了ApplicationListener接口
   // 是则加入当前的applicationContext的applicationListeners列表
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
   // 检查容器中是否包含名称为loadTimeWeaver的bean,实际上是增加Aspectj的支持
   // AspectJ采用编译期织入、类加载期织入两种方式进行切面的织入
   // 类加载期织入简称为LTW(Load Time Weaving),通过特殊的类加载器来代理JVM默认的类加载器实现
   if (!IN_NATIVE_IMAGE && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // 如果定义了则添加loadTimeWeaver功能的beanPostProcessor扩展 并且创建一个临时的classLoader来让其处理真正的bean
      //spring的loadTimeWeaver主要是通过 instrumentation 的动态字节码增强在装载期注入依赖
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
   // 添加默认的系统环境bean
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
   if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
      beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
   }
}

ResourceEditorRegistrar 类的 registerCustomEditors方法注册了一系列的常用类型的属性编辑器
如:doRegisterEditor(registry,Class.class, new ClassEditor(classLoader))实现的功能就是注册 Class类对应的属件编辑器。那么,注册后,一旦某个实体bean中存在一些Class类型的属性, 那么Spring会调用ClassEditor将配置中定义的String类型转换为Class类型并进行陚值。通过这种方式我们可以去实现自己的属性编辑器。

3.2 、beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

/**
 *   接口BeanPostProcessor规定的方法,会在bean创建时,实例化后,初始化前,对bean对象应用
 */
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
         bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
         bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
         bean instanceof ApplicationStartupAware)) {
      return bean;
   }
   AccessControlContext acc = null;
   if (System.getSecurityManager() != null) {
      acc = this.applicationContext.getBeanFactory().getAccessControlContext();
   }
   if (acc != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         // 检查bean上是否实现了某个Aware接口,有的话做相应调用
         // 为啥不通过自动注入?在AbstractApplicationContext中设置了aware的接口忽略注入
         invokeAwareInterfaces(bean);
         return null;
      }, acc);
   }
   else {
      invokeAwareInterfaces(bean);
   }
   return bean;
}
/**
* 设置所有的aware属性
*/
private void invokeAwareInterfaces(Object bean) {
   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);
   }
   if (bean instanceof ApplicationStartupAware) {
      ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
   }
   if (bean instanceof ApplicationContextAware) {
      ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
   }
}

ApplicationContextAwareProcessor主要作用就是在beanFactory bean初始化的时候调用各个Aware接口。

未完待续。。。。。。。。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 11:30:08  更:2021-07-29 11:31:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 15:16:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码