Spring源代码解析(一)Spring中的事务处理
- 格式:doc
- 大小:181.00 KB
- 文档页数:15
Spring声明式事务详解Spring 中的事务控制⽅式Spring 的事务控制可以分为编程式事务控制和声明式事务控制编程式开发者直接把事务的代码和业务代码耦合到⼀起,在实际开发中不⽤。
声明式开发者采⽤配置的⽅式来实现的事务控制,业务代码与事务代码实现解耦合,使⽤的API思想。
基于XML的声明式事务控制【重点】在 Spring配置⽂件中声明式的处理事来代替代码式的处理事务。
底层采⽤ AOP 思想来实现的。
声明式事务控制明确事项:核⼼业务代码(⽬标对象)事务增强代码{ Spring已提供事务管理器)切⾯配置步骤分析1.引⼊tx 命名空间2.事务管理器通知配置3.事务管理器AOP配置引⼊依赖坐标<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/beanshttps:///schema/beans/spring-beans.xsd/schema/contexthttps:///schema/context/spring-context.xsd/schema/aophttps:///schema/aop/spring-aop.xsd/schema/txhttps:///schema/tx/spring-tx.xsd"></beans>基于 XML 的声明式事务的控制配置⽂件<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xmlns:aop="/schema/aop"xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/beanshttps:///schema/beans/spring-beans.xsd/schema/contexthttps:///schema/context/spring-context.xsd/schema/aophttps:///schema/aop/spring-aop.xsd/schema/txhttps:///schema/tx/spring-tx.xsd"><!-- 开启 IOC 注解扫描 --><context:component-scan base-package="inly"/><!-- 引⼊ properties ⽂件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置数据源 --><bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${ername}"/><property name="password" value="${jdbc.password}"/></bean><!-- jdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!-- 绑定数据源 --><property name="dataSource" ref="datasource"/></bean><!-- 事务管理器对象 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源对象 --><property name="dataSource" ref="datasource"/></bean><!-- 通知增强 transaction-manager: 配置的事务管理器对象 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 定义⼀些事务属性 --><tx:attributes><!-- * 表⽰当前任意名称的⽅法都⾛默认的配置 --><tx:method name="*"/></tx:attributes></tx:advice><!-- AOP 配置切⾯ --><aop:config><!-- 配置声明式式务 --><aop:advisor advice-ref="txAdvice" pointcut="execution(* erServiceImpl.updateUser(..))"/></aop:config></beans>Service 层@Overridepublic void updateUser() {User user = userDao.find(2);user.setName("li3");userDao.updateUser(user);int i = 1 / 0;user.setAge(13);userDao.updateUser(user);System.out.println(user);}事务参数的配置详解<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/> name:切点⽅法等isolation:事务的隔离级别propogation:事务的传播⾏为timeout:超时时间read-only:是否只读常⽤ CURD 配置<tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 定义⼀些事务属性 --><tx:attributes><!-- CRUD 常⽤配置表⽰以update开头的⽅法--><tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" timeout="-1"/> <tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" timeout="-1"/><tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" timeout="-1"/> <tx:method name="find" read-only="true"/><!-- * 表⽰当前任意名称的⽅法都⾛默认的配置 --><tx:method name="*"/></tx:attributes></tx:advice>基于注解的声明式事务控制常⽤注解步骤分析修改 Service 层,增加事务注解@Override@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ,readOnly = false,timeout = -1) public void updateUser() {User user = userDao.find(2);user.setName("li3");userDao.updateUser(user);int i = 1 / 0;user.setAge(13);userDao.updateUser(user);System.out.println(user);}修改 Spring 核⼼配置⽂件,开启事务注解⽀持<tx:annotation-driven/>。
spring事务实现原理Spring事务实现原理。
Spring框架是一个轻量级的开源框架,它为企业级应用程序提供了全面的基础设施支持。
其中,事务管理是Spring框架的一个重要特性,它能够帮助我们简化事务管理的复杂性,提高开发效率。
本文将深入探讨Spring事务的实现原理,帮助读者更好地理解Spring框架中事务管理的工作机制。
在Spring框架中,事务管理主要通过两种方式来实现,基于编程的事务管理和基于声明式的事务管理。
基于编程的事务管理是通过编写代码来控制事务的提交和回滚,而基于声明式的事务管理则是通过在配置文件中声明事务的属性来实现。
这两种方式都是基于Spring框架中的事务管理器来实现的。
Spring框架中的事务管理器是一个接口,它定义了事务管理的基本操作,包括事务的开始、提交和回滚。
在实际应用中,我们可以通过配置来指定具体的事务管理器实现,例如DataSourceTransactionManager、HibernateTransactionManager等。
这些事务管理器会根据具体的数据访问技术来管理事务,确保事务的一致性和隔离性。
在Spring框架中,事务管理的核心是通过AOP(面向切面编程)来实现的。
Spring框架利用AOP技术在方法调用前后插入事务管理的逻辑,从而实现了对事务的控制。
通过AOP,Spring框架能够将事务管理的逻辑与业务逻辑分离,使得事务管理变得更加灵活和可维护。
另外,Spring框架还提供了@Transactional注解来简化事务管理的配置。
通过在方法上添加@Transactional注解,我们可以将该方法纳入事务管理的范围之内,从而实现对该方法的事务控制。
这种基于注解的事务管理方式极大地简化了事务管理的配置工作,提高了开发效率。
除了事务管理器和AOP技术,Spring框架还依赖于底层的数据访问技术来实现事务管理。
不同的数据访问技术有着不同的事务管理实现方式,例如JDBC、Hibernate、JPA等。
以前说了大多的原理,今天来说下spring的事务管理器的实现过程,顺带源码干货带上。
其实这个文章唯一的就是带着看看代码,但是前提你要懂得动态代理以及字节码增强方面的知识(/xieyuooo/article/details/7624146),关于annotation在文章:/xieyuooo/article/details/8002321也有说明,所以本文也就带着看看代码而已。
关于annotation这里就不说了,我们看看平时一般会怎么样来配置spring的配置,通过配置文件反射源码如何看看。
一般来讲首先会配置一个datasource,至于你配置什么连接池还是用JNDI这里就不提到细节,总之我们认为配置的spring的全局名称为dataSource就可以了。
接下来会将datasource交给各种连接池的操作类,如:ibatis、jdbcTemplate等等,这些不是我们关心的重点,我们需要关心的是dataSource是谁来管理了,在spring中配置了给一个DataSourceTransactionManager的对象:<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource"><ref bean="dataSource" /></property></bean>ok,先记录下来,至于下面的NameMatchTransactionAttributeSource描述了那些情况要进行事务管理,我们将它理解为一种属性配置,在运行时需要解析即可,所以他也并不是我们特别需要的重点。
Spring核⼼系列之Spring中的事务Spring核⼼系列之Spring中的事Spring核⼼系列之Spring中的事务Hello,⼤家好,前⾯两篇⽂章给⼤家分享了Spring AOP,今天就趁热打铁,给⼤家分享⼀下,Spring中的事务,事务这个事,其实在国内⼀些⼩公司,⼀般都会忽略的,尤其是很多⽹站,设计不到钱的系统,不会在乎这个东西,事务不回滚造成的结果⽆⾮就是脏数据,脏改等后果。
因为作者以前待过的⼀个房产⽹站,根本就不在乎这个事务,有问题就有问题了,反正⽤户也没充钱在⽹站上。
呵呵。
今天还是和⼤家分享⼀下这个Spring的事务,因为这个东西算是Spring 内部使⽤AOP最好的⼀个体现,体现了AOP思想,OK,⽂章结构:Spring boot 中的事务Spring事务中的事务属性1. Spring boot 中的事务看到Spring boot,很多⼈肯定感觉是被忽悠了,为什么说讲Spring事务,这⼜来Spring boot搞事情。
⽤过Spring boot的⼩伙伴其实都知道,这两个没什么⼤的区别,笔者这⾥使⽤Spring boot来演⽰,完全是为什么了简便。
因为搭⼀个Spring传统的ssm三件套⼯程可能要花费5分钟,⽽搭建⼀个Spring boot的"ssm"⼯程,就是⿏标点⼀点的事。
⽽且开启事务也是⼀个注解的事。
所以,⽼铁们,对不住了,这⼀篇⽤Spring boot和⼤家演⽰Spring的事务,这⾥我给⼀个传送门,是传统项⽬的事务,⼤家可以参考下:传统Spring⼯程的Spring事务废话不多说,直接上Spring boot代码:.@EnableTransactionManagement 表⽰开启事务!.这是⼀个Service,内部的personMapper是⼀个dao接⼝,持久化⽤的mybatis.演⽰的效果应该是:当调⽤PersonService的testTx()时,由于开启了事务,所以update2报异常时,应该会回滚。
spring 事务实现原理Spring事务的实现原理主要依赖于数据库或者其他存储系统的事务功能。
1. 数据库事务支持:Spring事务的实现依赖于数据库的事务功能。
通常情况下,数据库支持ACID(原子性、一致性、隔离性和持久性)事务特性,可以通过SQL的BEGIN、COMMIT 和ROLLBACK等命令来控制事务的开始、提交和回滚操作。
2. 事务管理器:Spring框架提供了事务管理器(TransactionManager)接口,用于管理事务的开始、提交和回滚等操作。
事务管理器可以根据配置信息选择不同的实现,如使用JDBC事务管理器(DataSourceTransactionManager)或者JTA事务管理器(JtaTransactionManager)等。
3. 编程式事务:Spring框架提供了编程式事务管理的支持,通过编写代码显式地控制事务的边界。
开发者可以在代码中使用事务管理器的API来手动管理事务,包括事务的开始、提交和回滚等操作。
这种方式灵活性较高,但也需要开发者手动处理事务的细节。
4. 声明式事务:Spring框架还提供了声明式事务管理的支持,通过使用注解或者XML配置来定义事务的属性和边界。
开发者可以使用@Transactional注解或者事务配置元素来标记方法或者类,指示该方法或者类在执行时需要开启事务。
Spring会在方法调用前后自动地管理事务的开始、提交和回滚等操作。
5. 事务传播行为:Spring事务还支持事务传播行为的定义,即一个方法调用另一个带有事务的方法时事务该如何传播。
例如,当前方法可能会暂停事务、加入到现有的事务中或者创建一个新的事务。
Spring提供了多种事务传播行为的选项,如REQUIRED、REQUIRES_NEW、NESTED等,可以根据需要进行配置。
总的来说,Spring事务的实现原理是通过与数据库或其他存储系统的事务功能结合,通过事务管理器来管理事务的开始、提交和回滚等操作。
Spring源码分析-事件机制为了⽅便快速理解,我还是先不讲原理,直接⽰例开篇吧。
⼀、⽰例1.定义⼀个Listener 实现了ApplicationListener 接⼝@Componentpublic class MyTestListener implements ApplicationListener{@Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println("向zookeeper注册暴露的服务...");}}2.applicationContext.xml 添加如下内容<context:annotation-config /><context:component-scan base-package="com.event"/>3.测试public class SpringEventTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");}}控制台输出:在这⾥不知道⼤家有没有发现,我这个main⽅法除了new ClassPathXmlApplicationContext("classpath:applicationContext.xml");其它什么也没做,那么为何MyTestListener 中的 onApplicationEvent ⽅法就执⾏了?⼆、源码分析1.先在⾃定义的listener类的 onApplicationEvent ⽅法进⾏断点调试(这⾥主要是为了通过Debug模式的线程栈查看从执⾏main⽅法开始到最后执⾏onApplicationEvent ⽅法结束都调⽤了哪些⽅法)2.Debug 运⾏测试类3.通过 Debug 线程栈分析源码执⾏过程(这⾥展⽰从main⽅法开始到onApplicationEvent⽅法的调⽤过程)从这个线程栈中可以看出,执⾏到refresh ⽅法中的finishRefresh 时,即执⾏publishEvent,关于refresh ⽅法我在这⾥不做过多的说明。
Spring编程式事务详解为了更细粒度的事务划分,Spring提供如下两种⽅式的编程式事务管理:1 PlatformTransactionManager你也可以使⽤ org.springframework.transaction.PlatformTransactionManager 来直接管理你的事务。
只需通过bean的引⽤,简单的把你在使⽤的PlatformTransactionManager 传递给你的bean。
然后,使⽤TransactionDefinition和TransactionStatus对象, 你可以启动,回滚和提交事务。
DefaultTransactionDefinition def =new DefaultTransactionDefinition();// explicitly setting the transaction name is something that can only be done programmaticallydef.setName("SomeTxName");def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status = txManager.getTransaction(def);try{// 执⾏业务逻辑}catch(MyException ex){txManager.rollback(status);throw ex;}mit(status);2 TransactionTemplatePlatformTransactionManager中部分代码是可以重⽤的,所以spring对其进⾏了优化,采⽤模板⽅法模式就其进⾏封装,主要省去了提交或者回滚事务的代码。
若你选择编程式事务管理,Spring推荐使⽤ TransactionTemplate。
spring事务原理数据库系统内,事务指一系列连续的操作,这系列操作被看作一个整体,要么完全执行,要么完全不执行,不会出现执行部分的情况,这是数据库系统的基本特征之一。
在传统数据库系统中,事务的管理是由数据库系统自身提供的一种功能,然而随着数据库系统的复杂性的增加,数据库中的事务管理越来越复杂,对数据库操作有更多的要求,这样就催生了应用层事务管理技术,而当前最流行的事务管理技术是Spring事务。
Spring事务是一种基于AOP(面向切面编程)的分布式事务管理技术,它能够帮助系统更好的控制事务的处理过程,从而使系统内的数据更加有效率的共享,降低数据库事务的管理复杂度,提高数据库系统的可用性及性能。
Spring事务原理包括几个要素:事务模型、分布式事务处理框架、事务实现机制以及事务管理工具等。
一、事务模型Spring事务原理的核心是事务模型,即它把事务分为两种:提交成功事务和失败事务,在Spring提供的事务模型中,每个事务都只有两种结果,要么提交成功,要么提交失败,而不存在半提交的状态。
在Spring的事务模型中,事务的分类还要求事务的原子性,它要求一旦提交事务,事务就不会再次改变,或者改变的程度会很小。
原子性还表明事务的执行要么完全成功,要么完全失败,不会出现半成功半失败的情况。
二、分布式事务处理框架Spring提供了基于AOP技术的分布式事务处理框架,这种分布式事务处理框架能够有效地支持不同数据库之间的事务处理,它包括三个部分:事务管理器(TransactionManager)、事务拦截器(TransactionInterceptor)和事务事件监听器(TransactionListener)。
事务管理器是Spring对分布式事务的抽象,它可以处理不同类型的事务,它的实现通常会涉及到一些事务拦截器。
事务拦截器是Spring提供的一种安全机制,它能够在事务处理过程中,根据配置的规则,来拦截事务的执行,以便能够在事务处理过程中发现任何可能存在的问题,并对其进行调整,使得事务能够顺利的提交。
简述spring的事物管理原理
Spring的事务管理原理是基于AOP(面向切面编程)和代理模式实现的。
Spring的事务管理实现主要包括以下几个步骤:
1. 配置事务管理器:通过配置需要使用的事务管理器,如DataSourceTransactionManager或JtaTransactionManager,来管理事务。
2. 使用@Transactional注解标记事务方法:在需要进行事务管理的方法上添加@Transactional注解,Spring会通过AOP将该方法进行代理,以实现在方法执行前后进行事务的开启、提交或回滚。
3. 执行代理方法:当调用被@Transactional注解标记的方法时,实际执行的是代理对象的方法。
代理对象会在方法执行前后执行一系列的操作,包括开启事务、执行业务逻辑、提交事务或回滚事务。
4. AOP拦截:Spring使用AOP在代理对象的方法执行前后拦截方法调用,并根据方法上的@Transactional注解来判断是否需要进行事务管理。
5. 事务切面的应用:通过配置事务切面,将被@Transactional注解标记的方法组合为一个切面,然后在需要进行事务管理的地方将切面应用到目标对象上,实现对目标方法的事务管理。
总结起来,Spring的事务管理原理是通过AOP拦截方法调用,代理目标方法,并根据@Transactional注解的配置来进行事务的管理。
这样可以将事务的开启、提交或回滚等操作与业务逻辑解耦,提高代码的重用性和可维护性。
全面分析 Spring 的编程式事务管理及声明式事务管理摘要Spring 的事务管理是 Spring 框架中一个比较重要的知识点,该知识点本身并不复杂,只是由于其比较灵活,导致初学者很难把握。
本教程从基础知识开始,详细分析了 Spring 事务管理的使用方法,为读者理清思路。
先决条件本教程假定您已经掌握了 Java 基础知识,并对 Spring 有一定了解。
您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等。
本文将直接使用这些概念而不做详细解释。
另外,您最好掌握数据库的基础知识,虽然这不是必须的。
系统需求要试验这份教程中的工具和示例,硬件配置需求为:至少带有 512MB 内存(推荐 1GB)的系统。
需要安装以下软件:Sun JDK 5.0 或更新版本或 IBM Developer Kit for the Java 5 platform 版本。
Spring framework 2.5。
本教程附带的示例代码已经在 Spring 2.5.6 上测试过。
MySQL 5.0 或更新版本。
Spring 事务属性分析事务管理对于企业应用而言至关重要。
它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。
就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保证用户和银行的利益都不受损失。
在 Spring 中,事务是通过 TransactionDefinition 接口来定义的。
该接口包含与事务属性有关的方法。
具体如清单1所示:清单1. TransactionDefinition 接口中定义的主要方法public interface TransactionDefinition{int getIsolationLevel();int getPropagationBehavior();int getTimeout();boolean isReadOnly();}也许你会奇怪,为什么接口只提供了获取属性的方法,而没有提供相关设置属性的方法。
在认真学习Rod.Johnson的三部曲之一:<<Professional Java Development with the spring framework>>,顺便也看了看源代码想知道个究竟,抛砖引玉,有兴趣的同志一起讨论研究吧!在Spring中,IOC容器的重要地位我们就不多说了,对于Spring的使用者而言,IOC容器实际上是什么呢?我们可以说BeanFactory就是我们看到的IoC容器,当然了Spring为我们准备了许多种IoC容器来使用,这样可以方便我们从不同的层面,不同的资源位置,不同的形式的定义信息来建立我们需要的IoC容器。
在Spring中,最基本的IOC容器接口是BeanFactory –这个接口为具体的IOC容器的实现作了最基本的功能规定–不管怎么着,作为IOC容器,这些接口你必须要满足应用程序的最基本要求:Java代码1. p ublic interface BeanFactory {2.3. //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,4. //如果需要得到工厂本身,需要转义5. String FACTORY_BEAN_PREFIX = "&";6.7.8. //这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。
9. Object getBean(String name) throws BeansException;10.11. //这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。
12. Object getBean(String name, Class requiredType) throws BeansException;13.14. //这里提供对bean的检索,看看是否在IOC容器有这个名字的bean15. boolean containsBean(String name);16.17. //这里根据bean名字得到bean实例,并同时判断这个bean是不是单件18. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;19.20. //这里对得到bean实例的Class类型21. Class getType(String name) throws NoSuchBeanDefinitionException;22.23. //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来24. String[] getAliases(String name);25.26. }在BeanFactory里只对IOC容器的基本行为作了定义,根本不关心你的bean是怎样定义怎样加载的–就像我们只关心从这个工厂里我们得到到什么产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心这些。
如果要关心工厂是怎样产生对象的,应用程序需要使用具体的IOC容器实现- 当然你可以自己根据这个BeanFactory来实现自己的IOC容器,但这个没有必要,因为Spring已经为我们准备好了一系列工厂来让我们使用。
比如XmlBeanFactory就是针对最基础的BeanFactory的IOC容器的实现–这个实现使用xml来定义IOC容器中的bean。
Spring提供了一个BeanFactory的基本实现,XmlBeanFactory同样的通过使用模板模式来得到对IOC容器的抽象- AbstractBeanFactory,DefaultListableBeanFactory这些抽象类为其提供模板服务。
其中通过resource 接口来抽象bean定义数据,对Xml定义文件的解析通过委托给XmlBeanDefinitionReader来完成。
下面我们根据书上的例子,简单的演示IOC容器的创建过程:Java代码1. C lassPathResource res = new ClassPathResource("beans.xml");2. D efaultListableBeanFactory factory = new DefaultListableBeanFactory();3. X mlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);4. r eader.loadBeanDefinitions(res);这些代码演示了以下几个步骤:1. 创建IOC配置文件的抽象资源2. 创建一个BeanFactory3. 把读取配置信息的BeanDefinitionReader,这里是XmlBeanDefinitionReader配置给BeanFactory4. 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成,这样完成整个载入bean定义的过程。
我们的IoC容器就建立起来了。
在BeanFactory的源代码中我们可以看到:Java代码1. p ublic class XmlBeanFactory extends DefaultListableBeanFactory {2. //这里为容器定义了一个默认使用的bean定义读取器3. private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);4. public XmlBeanFactory(Resource resource) throws BeansException{5. this(resource, null);6. }7. //在初始化函数中使用读取器来对资源进行读取,得到bean定义信息。
8. public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {9. super(parentBeanFactory);10. this.reader.loadBeanDefinitions(resource);11. }我们在后面会看到读取器读取资源和注册bean定义信息的整个过程,基本上是和上下文的处理是一样的,从这里我们可以看到上下文和XmlBeanFactory这两种IOC容器的区别,BeanFactory往往不具备对资源定义的能力,而上下文可以自己完成资源定义,从这个角度上看上下文更好用一些。
仔细分析Spring BeanFactory的结构,我们来看看在BeanFactory基础上扩展出的ApplicationContext –我们最常使用的上下文。
除了具备BeanFactory的全部能力,上下文为应用程序又增添了许多便利:* 可以支持不同的信息源,我们看到ApplicationContext扩展了MessageSource* 访问资源, 体现在对ResourceLoader和Resource的支持上面,这样我们可以从不同地方得到bean定义资源* 支持应用事件,继承了接口ApplicationEventPublisher,这样在上下文中引入了事件机制而BeanFactory是没有的。
ApplicationContext允许上下文嵌套–通过保持父上下文可以维持一个上下文体系–这个体系我们在以后对Web容器中的上下文环境的分析中可以清楚地看到。
对于bean的查找可以在这个上下文体系中发生,首先检查当前上下文,其次是父上下文,逐级向上,这样为不同的Spring 应用提供了一个共享的bean定义环境。
这个我们在分析Web容器中的上下文环境时也能看到。
ApplicationContext提供IoC容器的主要接口,在其体系中有许多抽象子类比如AbstractApplicationContext为具体的BeanFactory的实现,比如FileSystemXmlApplicationContext和ClassPathXmlApplicationContext提供上下文的模板,使得他们只需要关心具体的资源定位问题。
当应用程序代码实例化FileSystemXmlApplicationContext的时候,得到IoC容器的一种具体表现–ApplicationContext,从而应用程序通过ApplicationContext来管理对bean的操作。
BeanFactory 是一个接口,在实际应用中我们一般使用ApplicationContext来使用IOC容器,它们也是IOC容器展现给应用开发者的使用接口。
对应用程序开发者来说,可以认为BeanFactory和ApplicationFactory在不同的使用层面上代表了SPRING提供的IOC容器服务。
下面我们具体看看通过FileSystemXmlApplicationContext是怎样建立起IOC容器的, 显而易见我们可以通过new来得到IoC容器:Java代码1. A pplicationContext = new FileSystemXmlApplicationContext(xmlPath);调用的是它初始化代码:Java代码1. p ublic FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)2. throws BeansException {3. super(parent);4. this.configLocations = configLocations;5. if (refresh) {6. //这里是IoC容器的初始化过程,其初始化过程的大致步骤由AbstractApplicationContext来定义7. refresh();8. }9. }refresh的模板在AbstractApplicationContext:Java代码1. p ublic void refresh() throws BeansException, IllegalStateException {2. synchronized (this.startupShutdownMonitor) {3. synchronized (this.activeMonitor) {4. this.active = true;5. }6.7. // 这里需要子类来协助完成资源位置定义,bean载入和向IOC容器注册的过程8. refreshBeanFactory();9. …………10. }这个方法包含了整个BeanFactory初始化的过程,对于特定的FileSystemXmlBeanFactory,我们看到定位资源位置由refreshBeanFactory()来实现:在AbstractXmlApplicationContext中定义了对资源的读取过程,默认由XmlBeanDefinitionReader来读取:Java代码1. p rotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {2. // 这里使用XMLBeanDefinitionReader来载入bean定义信息的XML文件3. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);4.5. //这里配置reader的环境,其中ResourceLoader是我们用来定位bean定义信息资源位置的6. ///因为上下文本身实现了ResourceLoader接口,所以可以直接把上下文作为ResourceLoader传递给XmlBeanDefinitionReader7. beanDefinitionReader.setResourceLoader(this);8. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));9.10. initBeanDefinitionReader(beanDefinitionReader);11. //这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理12. loadBeanDefinitions(beanDefinitionReader);13. }转到beanDefinitionReader中进行处理:Java代码1. p rotected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {2. Resource[] configResources = getConfigResources();3. if (configResources != null) {4. //调用XmlBeanDefinitionReader来载入bean定义信息。