本篇文章给大家带来的内容是关于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 !!!调用无参构造函数"); } }
<bean name="coffee" class="com.test.spring.Coffee"/>
@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的演示
<bean name="coffee" class="com.test.spring.Coffee" lazy-init="true" />
@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<String> beanNames = new ArrayList<String>(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<Boolean>() { @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);
本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的Java教程视频栏目!
以上是Spring lazy-init原理的分析(代码示例)的详细内容。更多信息请关注PHP中文网其他相关文章!

新兴技术对Java的平台独立性既有威胁也有增强。1)云计算和容器化技术如Docker增强了Java的平台独立性,但需要优化以适应不同云环境。2)WebAssembly通过GraalVM编译Java代码,扩展了其平台独立性,但需与其他语言竞争性能。

不同JVM实现都能提供平台独立性,但表现略有不同。1.OracleHotSpot和OpenJDKJVM在平台独立性上表现相似,但OpenJDK可能需额外配置。2.IBMJ9JVM在特定操作系统上表现优化。3.GraalVM支持多语言,需额外配置。4.AzulZingJVM需特定平台调整。

平台独立性通过在多种操作系统上运行同一套代码,降低开发成本和缩短开发时间。具体表现为:1.减少开发时间,只需维护一套代码;2.降低维护成本,统一测试流程;3.快速迭代和团队协作,简化部署过程。

Java'splatformindependencefacilitatescodereusebyallowingbytecodetorunonanyplatformwithaJVM.1)Developerscanwritecodeonceforconsistentbehavioracrossplatforms.2)Maintenanceisreducedascodedoesn'tneedrewriting.3)Librariesandframeworkscanbesharedacrossproj

要解决Java应用程序中的平台特定问题,可以采取以下步骤:1.使用Java的System类查看系统属性以了解运行环境。2.利用File类或java.nio.file包处理文件路径。3.根据操作系统条件加载本地库。4.使用VisualVM或JProfiler优化跨平台性能。5.通过Docker容器化确保测试环境与生产环境一致。6.利用GitHubActions在多个平台上进行自动化测试。这些方法有助于有效地解决Java应用程序中的平台特定问题。

类加载器通过统一的类文件格式、动态加载、双亲委派模型和平台无关的字节码,确保Java程序在不同平台上的一致性和兼容性,实现平台独立性。

Java编译器生成的代码是平台无关的,但最终执行的代码是平台特定的。1.Java源代码编译成平台无关的字节码。2.JVM将字节码转换为特定平台的机器码,确保跨平台运行但性能可能不同。

多线程在现代编程中重要,因为它能提高程序的响应性和资源利用率,并处理复杂的并发任务。JVM通过线程映射、调度机制和同步锁机制,在不同操作系统上确保多线程的一致性和高效性。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

Dreamweaver CS6
视觉化网页开发工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

SublimeText3汉化版
中文版,非常好用