| |
|
开发:
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概述 -> 正文阅读 |
|
[Java知识库]Spring概述 |
Spring优点1) 轻量级开源的javaEE框架,简化企业应用开发复杂性; IoC容器作用:1) 控制反转:把对象创建和对象之间的调用过程交给Spring管理。 Spring Bean在Spring中,构成应用程序主干并由Spring IoC容器创建管理的对象称为Bean。 定义Spring Bean的方式1) 基于XML的方式
2) 基于注解扫描这种配置方式主要适用于:在开发中需要引用的类,如Controller、Service、Dao等。
?3) 基于Java配置可以通过代码控制对象创建,实现零配置,消除XML配置文件。
上面配置含义如下: Spring容器如何加载Bean?首先,Spring解析Bean配置信息,然后将配置信息转化为BeanDefinition对象,BeanDefinition保存了配置的所有内容,再将BeanDefinition存入BeanDefinitionMap中,这个Map以beanName作为key,以BeanDefinition作为value。之后每次获取bean对象,Spring容器就会根据beanName去Map中取对应的BeanDefinition对象。 Spring Bean的定义包含哪些内容?1) Spring Bean声明式配置内容 Spring Bean的配置内容有很多,主要有下面九个关键配置属性:class,scope,lazy-init,depends-on,bean-name,constructor-arg,properties,init-method,destroy-method。 这些属性都是在Spring配置文件中声明的内容,在Spring容器启动后,这些配置内容都将映射为BeanDefinition对象,然后将BeanDefinition对象保存到BeanDefinitionMap容器中,这个Map容器以beanName作为key,以BeanDefinition作为value。这样Spring容器创建对象时,就不需要再读取和解析配置文件,直接根据beanName就可以拿到对应的BeanDefinition对象,然后根据配置信息进行对象的实例化。 2) 配置文件与BeanDefinition映射关系 配置文件九个关键配置属性:class,scope,lazy-init,depends-on,bean-name,constructor-arg,properties,init-method,destroy-method,从下图可以看出,配置文件配置属性与BeanDefinition对象属性一一对应。 lazy-init:用于指定Bean实例是否延时加载,默认false,也就是说容器启动时就会创建Bean的实例,如果设置为true,那么只有在首次获取Bean时才会创建。 depends-on:用于定义Bean实例化的依赖关系,所依赖的Bean需要提前实例化;这里定义的数组类型,所以可以同时定义多个依赖对象,并且可以定义依赖顺序。 factoryBeanName:beanName,Bean的唯一标识,且不能以大写字母开头;如果没有设置,Spring默认使用类名首字母小写作为唯一标识。 3) Spring如何解析配置文件 Spring容器启动后,会调用BeanDefinitionReader工具类的loadBeanDefinitions()方法,对配置文件进行加载和解析。BeanDefinitionReader的主要作用是读取Spring配置文件中的内容,将其转换为BeanDefinition对象。BeanDefinitionReader有多个实现类,分别对应不同类型的配置,如:读取XML文件的XmlBeanDefinitionReader;读取属性文件的PropertiesBeanDefinitionReader;读取Groovy语言定义的GroovyBeanDefinitionReader。 为什么Spring中每个Bean都要定义作用域?1) Spring Bean的作用域有哪些 在Spring配置中,通过Definition对象中的scope属性来定义Bean的作用域,有5个作用域: a、singleton(默认):定义一个Bean为单例,在Spring IoC容器中只有唯一的实例,作用域范围是ApplicationContext容器 b、prototype:定义一个Bean为多例,即每次请求获取Bean都会重新创建实例,作用域是getBean方法直至获取对象 c、request:定义Bean的作用范围仅在request中,即每次Http请求会创建一个实例,该实例只在当前request中有效,作用域范围是每次发起HTTP请求直至拿到结果 d、session:定义Bean的作用范围仅在session中,即每次Http请求会创建一个实例,该实例在当前会话session中有效,作用域范围是浏览器首次访问直至浏览器关闭 e、globalsession:全局,该实例仅存于WebApplicationContext中,作用域范围是WebApplicationContext容器 2) Spring为什么定义作用域? 定义Bean的作用域,那么用户可以通过配置的方式设置Bean何时被创建,以及Bean的作用范围,从而起到保护Bean的作用。 Spring中的Bean是线程安全的吗?1) Spring中的Bean从何而来? 除了Spring框架内置Bean之外,其他Bean都是由我们自己通过Spring配置来声明的,Spring根据我们声明的配置信息(如:class,scope,lazy-init,depends-on,bean-name,constructor-arg,properties,init-method,destroy-method)进行解析转换成BeanDefinition,最终创建实例,由Spring IoC容器管理。所以说,Bean是否线程安全和Spirng容器无关,而是取决于我们声明的配置(如scope作用域)。 2) Spring中什么样的Bean存在线程安全问题? 线程安全问题和我们声明的Bean的作用域有直接关系,prototype多例Bean是每次请求都会创建新的实例,所以互不影响,不存在线程安全问题。 而singleton单例Bean是容器内唯一实例,所有线程共享,则可能存在线程安全问题,这取决于Bean是否有状态,如果是有状态的Bean,则会存在线程安全问题,无状态的Bean不存在线程安全问题。 有状态的Bean:在多线程操作中如果需要对Bean中的成员变量进行数据更新,这样的Bean是有状态的。 无状态的Bean:在多线程操作中,只会对Bean的成员变量进行查询操作,不修改成员变量的值,这样的Bean是无状态的。 3) 如何处理Spring Bean的线程安全问题? a、多例Bean没有线程安全问题,单例Bean可能存在线程安全问题,那么将单例Bean改成多例Bean即可 Spring Bean的生命周期全过程1) 创建前准备阶段 Bean加载之前,从Spring上下文和配置中获取Bean配置信息;如init-method(容器在初始化bean时调用的方法),destroy-method(容器在销毁实例时调用的方法)。还有实例化BeanFacoryPostProcesser和BeanPostProcessor,在bean加载过程中的前置和后置处理。这些类是Spring提供给开发者用于做扩展的,很多和Spring集成的中间件都会用到。 2) 创建实例阶段 通过反射来创建Bean的实例,并扫描和解析Bean的属性。 3) 依赖注入阶段 如果Bean存在其他依赖(depends-on配置有依赖关系),就需要对这些被依赖的Bean进行注入。比如通过@Autowired,@Resource等依赖注入的注解配置。注入过程中会调用BeanNameAware的setBeanName()方法给Bean设置name,调用BeanFactoryAware的setBeanFactory()方法创建Bean的Facotory,然后通过BeanFactory创建Bean实例。 此阶段还会触发一些扩展方法的调用,比如BeanPostProcessor,InitializingBean的afterPropertiesSet()方法给属性赋值,还有BeanFactoryAware等。 4) 容器缓存阶段 这个阶段把Bean保存到IoC容器中缓存起来,此时的Bean可以被使用了。此时Bean属性配置的init-method方法会被调用,BeanPostProcessor的初始化后后置处理器方法postProcessorAfterInitialization()会被调用。AOP正是通过此后置处理器实现。 5) 销毁实例阶段 将销毁Spring上下文的所有Bean,Bean中配置的destroy-method方法会被调用。 Spring为什么需要三级缓存解决循环依赖,而不是二级缓存? AOP |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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年11日历 | -2024/11/23 22:44:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |