热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Springlazyinit原理的分析(代码示例)

本篇文章给大家带来的内容是关于Springlazy-init原理的分析(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
本篇文章给大家带来的内容是关于Spring lazy-init原理的分析(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

普通的bean的初始化是在容器启动初始化阶段执行的,而被lazy-init修饰的bean 则是在从容器里第一次进行context.getBean(“”)时进行触发。Spring 启动的时候会把所有bean信息(包括XML和注解)解析转化成Spring能够识别的BeanDefinition并存到Hashmap里供下面的初始化时用。接下来对每个BeanDefinition进行处理,如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进行初始化并依赖注入。

本文我说了很多次 Spring 容器初始化bean初始化,容器的初始化有可能包括bean的初始化主要取决于该bean是否是懒加载的,特此说明怕误会 。。。:)

一.先睹为快

话不多说先写个例子看下这属性到底有什么作用,我们定义了一个叫做coffee的普通bean,代码如下:

1.普通非懒加载bean的演示

package com.test.spring;

public class Coffee {

    public Coffee() {
        System.out.println("正在初始化bean !!!调用无参构造函数");
    }
    
}
@Test
public void testLazyInit() {

    System.out.println("开始初始化Spring容器 ");
    // 非懒加载的bean会在容器初始化时进行bean的初始化,后面会拿Spring启动时的源码进行分析
    ApplicationContext cOntext= new ClassPathXmlApplicationContext("spring-beans.xml");
   // 非懒加载的bean 的构造函数会在这个位置打印
    System.out.println("Spring容器初始化完毕");
    
   System.out.println("开始从容器中获取Bean");

   Coffee coffee = context.getBean("coffee", Coffee.class);

   System.out.println("获取完毕  bean :" + coffee);
}

运行结果如下:

2.非懒加载bean的演示

@Test
    public void testLazyInit() {

        System.out.println("开始初始化Spring容器 ");
     // 在初始化容器阶段不会对懒加载的bean进行初始化
        ApplicationContext cOntext= new ClassPathXmlApplicationContext("spring-beans.xml");
  
        System.out.println("Spring容器初始化完毕");

        System.out.println("开始从容器中获取Bean");
     // 在这一阶段会对懒加载的bean进行初始化
        Coffee coffee = context.getBean("coffee", Coffee.class);

        System.out.println("获取完毕  bean :" + coffee);


    }

运行结果如下:

Spring 启动时主要干俩件事 1.初始化容器 2.对bean进行初始化并依赖注入。(懒加载的bean不做第二件)

但是对于大多数bean来说,bean的初始化以及依赖注入就是在容器初始化阶段进行的,只有懒加载的bean是当应用程序第一次进行getBean时进行初始化并依赖注入。下面贴出代码看下

Spring 容器初始化代码如下就一行:

ApplicationContext cOntext= new ClassPathXmlApplicationContext("spring-beans.xml");
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            // Spring ioc 启动入口 了解了refresh 就了解了ioc
            refresh();
        }
    }

Spring 初始化入口 refresh(省略了部分根本次无关的代码,望理解,太长了影响阅读体验)

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);
                // Instantiate all remaining (non-lazy-init) singletons.
                // 初始化所有非 懒加载的bean!!!!
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }
 }

第20行则是跟本次主题有关的,就是说在容器启动的时候 只处理 non-lazy-init bean,懒加载的bean在Spring启动阶段根本不做任何处理下面看下源码就明白了

点进去第20行的finishBeanFactoryInitialization(beanFactory)里头有个初始化non-lazy-init bean的函数 preInstantiateSingletons()

具体逻辑如下

1.对beanNames 集合遍历获取每个BeanDefinition

2.判断是否是懒加载的,如果不是则继续处理(non-lazy-init bean 不做处理)

3.判断是否是factorybean 如果不是则进行实例化并依赖注入

public void preInstantiateSingletons() throws BeansException {
   // 所有beanDefinition集合
   List beanNames = new ArrayList(this.beanDefinitionNames);
   // 触发所有非懒加载单例bean的初始化
   for (String beanName : beanNames) {
       // 获取bean 定义
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      // 判断是否是懒加载单例bean,如果是单例的并且不是懒加载的则在Spring 容器
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          // 判断是否是FactoryBean
         if (isFactoryBean(beanName)) {
                final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                   isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
                      @Override
                      public Boolean run() {
                         return ((SmartFactoryBean) factory).isEagerInit();
                      }
                   }, getAccessControlContext());
                }
         }else {
             // 如果是普通bean则进行初始化依赖注入,此 getBean(beanName)接下来触发的逻辑跟
             // context.getBean("beanName") 所触发的逻辑是一样的
            getBean(beanName);
         }
      }
   }
}

getBean() 方法是实现bean 初始化以及依赖注入的函数

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

三,总结

对于被修饰为lazy-init的bean Spring初始化阶段不会进行init并且依赖注入,当第一次进行getBean时候进行初始化并依赖注入

对于非懒加载的bean getBean的时候会从缓存里头取 因为容器初始化阶段已经初始化了

// 容器启动初始化 会初始化并依赖注入非懒加载的bean
   ApplicationContext cOntext= new ClassPathXmlApplicationContext("spring-beans.xml");
// lazy-init bean会进行第一次初始化并依赖注入  其他的会从缓存里取
   Coffee coffee = context.getBean("coffee", Coffee.class);

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注的Java教程视频栏目!

以上就是Spring lazy-init原理的分析(代码示例)的详细内容,更多请关注其它相关文章!


推荐阅读
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • Principle for Mac(交互式屏幕设计软件)免激活版
    Mac上好用的交互式屏幕设计软件,PrincipleforMac是一款交互式屏幕设计软件,principle mac让您的设计将以原则出现,随时为您注入新的活力。如果您进行更改,再 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文是关于自学Android的笔记,包括查看类的源码的方法,活动注册的必要性以及布局练习的重要性。通过学习本文,读者可以了解到在自学Android过程中的一些关键点和注意事项。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
author-avatar
酷的带_201
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有