Spring应用原理以及粗读源码系列一框架总述以Bean为核心的机制IoC容器初始化以及依赖注入.docx
- 文档编号:23969022
- 上传时间:2023-05-23
- 格式:DOCX
- 页数:76
- 大小:567.31KB
Spring应用原理以及粗读源码系列一框架总述以Bean为核心的机制IoC容器初始化以及依赖注入.docx
《Spring应用原理以及粗读源码系列一框架总述以Bean为核心的机制IoC容器初始化以及依赖注入.docx》由会员分享,可在线阅读,更多相关《Spring应用原理以及粗读源码系列一框架总述以Bean为核心的机制IoC容器初始化以及依赖注入.docx(76页珍藏版)》请在冰豆网上搜索。
Spring应用原理以及粗读源码系列一框架总述以Bean为核心的机制IoC容器初始化以及依赖注入
Spring应用、原理以及粗读源码系列
(一)--框架总述、以Bean为核心的机制(IoC容器初始化以及依赖注入)
总述:
spring框架是如今J2EE开发最重要框架之一,为企业级应用提供一系列轻量级解决方案,比如:
基于依赖注入的核心机制、基于AOP的声明式事务管理、与多种持久层技术整合、整合后端各种组件等等。
贯穿了表现层、业务层、持久层,实现无缝整合。
文章结构:
(1)框架总述;
(2)以Bean为核心的IOC/DI机制;
一、框架总述:
(1)CoreContainer(核心容器):
包含有Core,Beans,Context,ExpressionLanguage模块。
是框架的基础部分,提供IOC(控制反转)和依赖注入特性。
这里的基础概念是BeanFactory,它提供Factory模式的经典实现来消除对程序单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
Core模块主要包含Spring框架基本的核心工具类,Spring的其他组件都要使用到这个包里的类,Core模块是其他组件的基本核心。
当然你也可以在自己的应用系统中使用这些工具类。
Beans模块是所有应用都要用到的,它包含访问配置文件,创建和管理bean以及进行InversionofControl/DependencyInjection(依赖注入)操作相关的所有类。
Context模块构建于Core和Beans模块基础之上,提供了一种类似于JNDI注册器的框架式的对象访问方法。
Context模块集成了Beans的特性,为Spring核心提供了大量的扩展,添加了对国际化(例如资源绑定),事件传播,资源加载和对Context的透明创建的支持。
Context模块同时也支持J2EE的一些特性,例如EJB(java企业Bean),JMX(JavaManagementExtensions,即Java管理扩展是一个为应用程序、设备、系统等植入管理功能的框架)和基础的远程处理。
ApplicationContext接口是Context模块的关键。
ExpressionLanguage模块提供了一个强大的表达式语言用于在运行时查询和操纵对象。
它是JSP2.1规范中定义的unifedexpressionlanguage的一个扩展。
该语言支持设置/获取属性的值,属性的分配,方法的调用,访问数组上下文(accessionthecontextofarrays),容器和索引器,逻辑和算数运算符,命名变量以及从Spring的IOC容器中根据名称检索对象。
它也支持list投影,选择和一般的list聚合。
(2)WEB层:
Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。
所以Spring框架支持与JakartaStruts的集成。
Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Web层包含了Web,Web-Servlet,Web-Struts和Web-Porlet模块,具体说明如下。
Web-Servlet模块web.servlet.jar:
该模块包含Spring的model-view-controller(MVC)的实现。
Spring的MVC框架使得模型范围内的代码和webforms之间能够清楚地分离开来,并与Spring框架的其他特性集成在一起。
Web模块:
提供了基础的面向Web的集成特性。
例如,多文件上传,使用servletlisteners初始化IOC容器以及一个面向Web的应用上下文。
它还包含Spring远程支持中Web的相关部分。
Web-Porlet模块:
提供了用于Portlet环境和Web-Servlet模块的MVC的实现。
spring4.0以后加入了对websocket技术的支持.目的是浏览器与服务端建立全双工的通信方式,解决http请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天、股票交易、游戏等对对实时性要求较高的行业领域。
(3)DataAccess/Integration.持久层:
DataAccess/Integration层包含有JDBC,ORM,OXM,JMS和Transaction模块,其中:
JDBC模块提供了一个JDBC抽象层,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码。
这个模块包含了Spring对JDBC数据访问进行封装的所有类。
ORM(ObjectRelationalMapping对象关系映射)模块为流行的对象-关系映射API,如JPA,JDO,Hibernate,iBatis等,提供了一个交互层。
利用ORM封装包,可以混合使用所有Spring提供的特性进行O/R映射。
如前边提到的简单声明性事务管理。
Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO,hibernate和MyBatis。
所有这些都遵从Spring的通用事务和DAO异常层次结构。
OXM模块提供了一个对Object/XML映射实现的抽象层,Object/XML映射实现包括JAXB(JAXB能够使用Jackson对JAXB注解的支持实现(jackson-module-jaxb-annotations),既方便生成XML,也方便生成JSON,这样一来可以更好的标志可以转换为JSON对象的JAVA类。
JMS(JavaMessagingService)模块主要包含了一些制造和消费消息的特性。
Transaction模块支持编程和声明性的事务管理,这些事务类必须实现特定的接口,并且对所有的POJO(实际就是普通JavaBeans)都适用。
(4)切面层:
1.AOP模块提供了一个符合AOP联盟标准的面向切面编程的实现,它让你可以定义例如方法拦截器和切点。
从而将逻辑代码分开,降低它们之间的耦合性。
利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中,这有点像.Net技术中的attribute概念。
通过配置管理特性,SpringAOP模块直接将面向切面的编程功能集成到了Spring框架中,所以可以很容易地使Spring框架管理的任何对象支持AOP。
SpringAOP模块为基于Spring的应用程序中的对象提供了事务管理服务。
通过使用SpringAOP,不用依赖EJB组件,就可以将声明性事务管理集成到应用程序中。
2.Aspects模块提供了对AspectJ(一个面向切面的框架,它扩展了Java语言)的集成支持。
3.Instrumentation模块提供了classinstrumentation支持和classloader实现,使得可以在特定的应用服务器上使用。
(5)Test层:
此层支持使用JUnit和TestNG对Spring组件进行测试。
@RunWith(SpringJUnit4ClassRunner.class)//使用Springtest测试框架
@ContextConfiguration("/spring/spring-*.xml")//加载配置
二、以Bean为核心的IOC/DI机制:
总述理论核心:
在spring中,所有的对象都会被spring核心容器管理。
一切对象统称为Bean。
Spring容器可通过XML配置文件或者注解去管理这堆Bean。
(1)定义以及原理:
依赖注入(IOC/DI):
spring容器负责将被依赖对象赋值给调用者的成员变量–相当于为调用者注入它依赖的实例。
依赖关系:
A对象需要调用B对象方法的情况–A依赖B。
原理:
1.原始做法:
调用者主动创建被依赖对象,然后再调用被依赖对象的方法。
调用者需要通过像“new对象”的操作去创建对象。
缺点:
必然导致调用者与被依赖对象实现类的硬编码耦合。
(因为我不想知道你的创建过程、也不想主动去创建你)
2.简单工厂模式:
调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖对象,最后再调用被依赖对象的方法。
调用者面向被依赖对象的接口编程;将被依赖对象的创建交给工厂;调用者通过工厂来获得被依赖组件。
缺点:
调用组件需要主动通过工厂去获取被依赖对象,必然带来调用组件与被依赖对象工厂的耦合。
(同样,我也不想知道你这个工厂存在,我只想要个依赖对象)
3.Spring框架下的依赖注入:
框架为调用者注入它依赖的实例。
优点:
程序无须例会被依赖对象的实现,也无须主动定位工厂。
只需被动等待IOC容器分配依赖对象。
(2)应用:
依赖注入分为两种:
[一]设值注入;[二]构造注入;
1.设值注入:
指IOC容器通过成员遍历的setter方法来注入被依赖对象。
使用方法:
可见我们没有硬编码上去创建依赖对象
xmlversion="1.0"encoding="GBK"?
>
--Spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束-->
xsi="http: //www.w3.org/2001/XMLSchema-instance" xmlns="http: //www.springframework.org/schema/beans" xsi: schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-4.0.xsd"> --配置chinese实例,其实现类是Chinese类--> --驱动调用chinese的setAxe()方法,将容器中stoneAxe作为传入参数--> --配置Axe实例--> publicclassChinese { privateAxeaxe;//定义个斧头引用 //设值注入所需的setter方法 publicvoidsetAxe(Axeaxe) { this.axe=axe; } //实现依赖对象的方法useAxe方法 publicvoiduseAxe() { //调用axe的chop()方法, //表明Chinese对象依赖于axe对象 System.out.println(axe.chop()); } } //斧头类 publicclassAxe { publicStringchop() { return"石斧砍柴好慢"; } } 写个test类 publicclassBeanTest { publicstaticvoidmain(String[]args)throwsException { //创建Spring容器 ApplicationContextctx=new ClassPathXmlApplicationContext("beans.xml"); //获取chinese实例 Chinesep=ctx.getBean("chinese",Chinese.class); //调用useAxe()方法 p.useAxe(); } } 2.构造注入: IOC容器使用构造器来注入被依赖对象。 在构造实例时,已经为其完成了依赖关系的初始化。 本质就是当执行带参数的构造器时,就可利用构造器参数对成员变量执行初始化。 《contructopr-arg…/》 使用方法: xmlversion="1.0"encoding="GBK"? > xsi="http: //www.w3.org/2001/XMLSchema-instance" xmlns="http: //www.springframework.org/schema/beans" xsi: schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-4.0.xsd"> --配置chinese实例,其实现类是Chinese--> --下面只有一个constructor-arg子元素, 驱动Spring调用Chinese带一个参数的构造器来创建对象--> --配置Axe实例--> publicclassChinese { privateAxeaxe; //构造注入所需的带参数的构造器 publicChinese(Axeaxe) { this.axe=axe; } //实现依赖对象的方法useAxe()方法 publicvoiduseAxe() { //调用axe的chop()方法 //表明Chinese对象依赖于axe对象 System.out.println(axe.chop()); } } publicclassAxe { publicStringchop() { return"石斧砍柴好慢"; } } 3.注解注入装配: 以后再讲,其实是基于前两种注解方式实现的。 (3)IOC/DI依赖注入源码理解: (基于spring4.1.7) 重点理解两个过程: IoC容器初始化过程以及IoC容器依赖注入过程。 其实就是: 资源定位、资源装载、资源解析、Bean生成,Bean注册、Bean依赖注入这几个过程(前五属于初始化过程)。 方法: eclipse断点ClassPathXmlApplicationContext调用,不断跳进去,就看到spring执行栈了。 1.IoC容器初始化过程: [一]资源定位: 追踪: 我们可在此句获取工厂前设断点然后debug追踪进去,查看IoC的资源定位 ApplicationContextctx=newClassPathXmlApplicationContext("/spring/spring-*.xml"); 1 1 然后一路跳进去: publicClassPathXmlApplicationContext(StringconfigLocation)throwsBeansException{ this(newString[]{configLocation},true,(ApplicationContext)null); } /* 此处为资源定位核心调用层 */ publicClassPathXmlApplicationContext(String[]configLocations,booleanrefresh,ApplicationContextparent)throwsBeansException{ super(parent);//有前面类图可以知道,最终父类为AbstractApplicationContext this.setConfigLocations(configLocations);//调用资源定位设置方法,然后我们跳进去寻找此方法位置,如下面代码 if(refresh){//接着执行容器刷新方法 this.refresh(); } } //这个是追踪上去的ClassPathXmlApplicationContext父类 publicAbstractXmlApplicationContext(ApplicationContextparent){ super(parent); } //再追踪AbstractXmlApplicationContext的父类AbstractRefreshableConfigApplicationContext。 然后它拥有了以下方法,从而 publicvoidsetConfigLocation(Stringlocation){ this.setConfigLocations(StringUtils.tokenizeToStringArray(location,",;\t\n")); } /* 资源定位方法 */ publicvoidsetConfigLocations(String...locations){ if(locations! =null){ Assert.noNullElements(locations,"Configlocationsmustnotbenull"); this.configLocations=newString[locations.length]; //该方法调用SystemPropertyUtils.resolvePlaceholders(path);对path中的占位符进行替换,eg: path路径中含有${user.dir},则将替换为: System.getProperty(user.dir); for(inti=0;i this.configLocations[i]=this.resolvePath(locations[i]).trim(); } }else{ this.configLocations=null; } } publicvoidrefresh()throwsBeansException,IllegalStateException{ Objectvar1=this.startupShutdownMonitor; //加锁同步了 synchronized(this.startupShutdownMonitor){ //调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识 this.prepareRefresh(); //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动 //并获取beanFactory ConfigurableListableBeanFactorybeanFactory=this.obtainFreshBeanFactory(); //为BeanFactory配置容器特性,例如类加载器、事件处理器等 this.prepareBeanFactory(beanFactory); try{ //为容器的某些子类指定特殊的BeanPost事件处理器 this.postProcessBeanFactory(beanFactory); //调用所有注册的BeanFactoryPostProcessor的Bean this.invokeBeanFactoryPostProcessors(beanFactory); //为BeanFactory注册BeanPost事件处理器. //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件 this.registerBeanPostProcessors(beanFactory); //初始化信息源,和国际化相关. this.initMessageSource(); //初始化容器事件传播器. this.initApplicationEventMulticaster(); //调用子类的某些特殊Bean初始化方法 this.onRefresh(); //为事件传播器注册事件监听器. this.registerListeners(); //初始化所有剩余的单态Bean. this.finishBeanFactoryInitialization(beanFactory); //初始化容器的生命周期事件处理器,并发布容器的生命周期事件 this.finishRefresh(); }catch(BeansExceptionvar5){ //打印警告 this.logger.warn("Exceptionencounteredduringcontextinitialization-cancellingrefreshattempt",var5); //销毁以创建的单态Bean this.destroyBeans(); //取消refresh操作,重置容器的同步标识. this.cancelRefresh(var5); throwvar5; } } } //获取工厂,让子类刷新内部bean工厂。 /* 关闭前面所有bean工厂,为新的上下文环境初始化一个新的bean工厂。 这里需要子类来协助完成资源位置定义,bean载入和向IOC容器注册的过程 容器真正调用的是其子类AbstractRefreshableApplicationContext实现的refreshBeanFactory()方法 见下方 */ protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){ this.refreshBeanFactory();//子类实现,调用子类的实现 ConfigurableListableBeanFactorybeanFactory=this.getBeanFactory(); if(this.logger.isDebugEnabled()){ this.logger.debug("Beanfactoryfor"+this.getDisplayName()+": "+beanFactory); } returnbeanFactory; } AbstractRefreshableApplicationContext实现的refreshBeanFactory /* 在这个方法中,先判断BeanFactory是否存在,如果存在则先销毁beans并关闭beanFactory,接着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean */ protectedfinalvoidrefre
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring 应用 原理 以及 源码 系列 框架 Bean 核心 机制 IoC 容器 初始化 依赖 注入
链接地址:https://www.bdocx.com/doc/23969022.html