1.「译」Spring 事务管理:@Transactional 深度解析|by MarcoBehler.md
2.Springä¸BeanFactoryä¸FactoryBeançä½ç¨ä¸åºå«
3.springçç»ä»¶åä½ç¨(springclouç»ä»¶)
「译」Spring 事务管理:@Transactional 深度解析|by MarcoBehler.md
原文链接为: Spring Transaction Management: @Transactional In-Depth | MarcoBehler
你可以通过本文,源码对@Transactional 注解在 Spring 事务管理中的源码运行机制,形成一个简明实用的源码理解。
唯一的源码阅读前提?你需要对数据库 ACID 原则有个大致了解,即数据库事务是源码什么,我们为什么需要它。源码163k 源码此外,源码本文没有覆盖分布式事务和反应式事务(reactive transactions),源码尽管在 Spring 中下文提到的源码一些通用原则也是适用的。
在本文中,源码你将学到 Spring 事务抽象框架的源码核心概念,同时会有很多示例代码帮助你理解。源码
相对于 Spring 官方文档,源码本文不会让你迷失在 Spring 的源码上层概念里。 相反你会以不同寻常的源码路径来学习 Spring 事务管理。从底层开始,一层层向上。也就是说,你将从普通原始的小说织梦源码 JDBC 事务学起。
普通的 JDBC 事务是如何工作的?如何 start, commit 或 rollback JDBC 事务?最终,他们都做了同样的事来开启和关闭(或称为“管理”)数据库事务。纯 JDBC 事务管理代码如下:这 4 行高度简化的代码,就是 Spring@Transactional 为你在背后做的所有事情。在下一章节中,你将会学到他们是如何工作的。在此之前,我们还有一丁点知识点要补充。
如何使用 JDBC 隔离级别和保存点(savepoints)?如果你已经使用过 Spring@Transactional 注解,你可能碰到过类似用法:我们会在后文更加详细的介绍 Spring 嵌套事务和隔离级别,在这重复提及,是因为这些参数最终可提炼成如下 JDBC 代码:
Spring 或 Spring Boot 的事务是如何工作的?既然现在你对 JDBC 事务有了基础的理解,让我们再去探究下纯粹的 Spring 核心事务。这里所讲都可 1:1 适用于 Spring Boot 和 Sring MVC,但又做了一些补充。到底什么是 Spring 事务管理或事务抽象框架?记住,事务管理可简单理解为:Spring 如何 start, commit 或 rollback JDBC 事务?是不是听着和前文讲得很相似?抓住重点:基于 JDBC 你只有一个方法(setAutocommit(false))来开启事务管理,Spring 提供了许多不同,php伪静态 源码但更方便的封装来做相同的事情。
如何使用 Spring 编程式事务管理?最初,但现在很少使用方式,是在 Spring 通过编程定义事务:通过TransactionTemplate 或者直接使用 PlatformTransactionManager。代码示例如下「译者注:参见配套项目 BookingServcie 实现」:与 JDBC 示例 比较:尽管这是一个不小的改进,但编程式事务管理并不是 Spring 事务框架主要关注的。相反,声明式事务管理才是重头戏。让我们一探究竟
如何使用 Spring 的@Transactional 注解(声明式事务管理)?让我们看下时下的 Spring 事务管理通常怎么用:这是怎么做到的?没有了冗余的 XML 配置和额外的编码。相反,你只需要做两件事:所以,为了让@Transactional 工作,你需要:现在,我说 Spring 透明的为你处理事务,到底在指什么? 在有了 JDBC 事务示例 的知识储备后,@Transactional 标注的 UserService 可以翻译简化成:这个示例看起来像魔术,让我们继续探究下 Spring 是如何为你自动插入这些连接代码的。
CGLIB & JDK 代理 - 在@Transactional 之下?Spring 不能真的安卓亮度源码像我上面做的那样,去重写你的 Java 类来插入连接代码(除非你使用字节码增强等高级技术,在这我们暂时忽略它)
你的registerUser() 方法还是只是调用了 userDao.save(user),这是无法实时改变的。但是 Spring 有它的优势。在核心层,它有一个 IoC 容器。它实例化一个UserService 单例并可自动注入到任何需要 UserService 的 Bean 中。不管何时你在一个 Bean 上使用@Transactional,Spring 使用了个小伎俩。它不是直接实例化一个 UserService 原始对象,而是一个 UserService 的事务代理对象。借助 Cglib library 的能力,它可以使用子类继承代理(proxy-through-subclassing)的方式来实现。当然还有其他方式可以构造代理对象(例如 Dynamic JDK proxies 「译者注:这要求代理对象有相应接口类」),这里暂不做展开。
你的UserService 可以动态生成代理类,并且代理可以帮你管理事务。但是电影播放软件源码并不是代理类本身去处理事务状态(open,commit,close),而是委托给了事务管理器(transaction manager)。
你的UserService 有一个 invoice() 事务方法。它调用了另外一个 InvoiceService 类上的 createPdf() 事务方法。然而从 Spring 看来,这里有 2 个逻辑事务存在:第一个在UserService,另外一个在 InvoiceService。Spring 足够智能知道让两个 @Transactional 标记的方法,在底层使用同一个物理数据库事务。
更改事务传播模式为requires_new 告诉 Spring:createPDF() 需要在它自己的、独立于其他任何已经在的事务里执行。这意味着你的底层代码会打开 2(物理)连接/事务 到数据库。Spring 依旧能够机智的把 2 个 逻辑事务( invoice()/createPdf() )映射到两个不同的物理数据库事务上。
每个 Spring 传播模式在 数据库或 JDBC 连接层面到底做了什么?练习: 在原始 Java 实现那节,我展示了 JDBC 能够对事务进行的所有操作。花几分钟思考下,每个 Spring 传播模式在数据库或 JDBC 连接层面到底做了什么。然后再看下下面的解答。
答案:如你所见,大多数传播模式并没有在数据库或 JDBC 层面做什么事情。更多的是通过 Spring 来组织你的代码,告诉 Spring 如何/什么时候/哪里需要事务处理。
在示例中,任何时候你调用UserService 的 myMethod() 方法,Spring 期望这里有一个打开的事务。它不会为自己开启,相反,在没有已开启事务的情况下调用方法,Spring 会抛出异常。请记住这 “逻辑事务处理”的补充知识点。
@Transactional 上隔离级别(Isolation Levels)代表什么?这是个抖机灵的问题,但当你如下配置的时候,到底发生了什么?哈,这可以简单地等价于:然而数据库事务隔离级别,是一个复杂的主题,你需要自己花些时间去掌握。Pstgres 的官方文档中的 isolation levels 章节,是个不错的入门文档。
最容易踩的@Transactional 的坑?这里有一个 Spring 新手经常踩的坑,看下如下代码:你有一个UserService 类,事务方法 invoice 内部调用了事务方法 createPdf()。所以,当有人调用invoice() 的时候,最终有个多少个物理事务被打开?答案不是 2 个,而是 1 个,为什么呢?让我们回到本文中代理那章节。Spring 为你创建了UserService 代理类,但代理类内部的方法调用,是无法被代理的。也就是说,没有新的事务为你生成。这里有技巧(例如: self-injection 「译者注:参见示例项目 InnerCallSercie」),可以帮助你绕过该限制。但主要收获是:始终牢记代理事务的边界。
在 Spring Boot 或 Spring MVC 中使用@Transactional?我们目前只是讨论了纯粹的核心 Spring 上的用法。那在 Spring Boot 或 Spring MVC 中会有什么使用差异吗?答案是:没有。无论使用何种框架(或更确切地说:Spring 生态系统中的所有框架),您都将始终使用 @Transactional 注解,配合事务管理器,以及@EnableTransactionManagement 注解。没有其他用法了。但是,与 Spring Boot 的唯一区别是,通过 JDBC 自动配置,它会自动设置@EnableTransactionManagement 注解,并为你创建 PlatformTransactionManager。
关于 Spring 回滚的部分,将会在下一次文章修订中补充。Spring Boot 内回滚是通过@Transactional 注解上 rollback 系列配置实现的,读者可查阅源码注释了解使用方式,注释还是写得很完备的,本质上也是根据配置条件,确定何时调用 commit,何时调用 rollback。
Spring 和 JPA / Hibernate 事务管理是如何一起工作的?目标:同步 Spring@Transactional 和 Hibernate / JPA。在这个节点上,你期望 Spring 可以和其他数据库框架,类似 Hibernate(一个流行的 JPA 实现)或 Jooq 等整合。让我来看一个纯粹的 Hibernate 示例(注意:直接使用 Hibernate 还是通过 JPA 使用 Hibernate 都没关系)。用 Hibernate 将UserService 重写如下:然而上述代码有一个大问题:但最终我们还是可以将 Spring 和 Hibernate 无缝整合,也就是说他们其实可以理解对象的事务概念。代码如下:这是怎么做到的?使用 HibernateTransactionManager 有一个非常简单的解决此集成问题的方法:相比在 Spring 配置里使用 DataSourcePlatformTransactionManager,你可以替换成 HibernateTransactionManager(如果使用了原生 Hibernate)或 JpaTransactionManager(如果通过 JPA 使用了 Hibernate)。这个定制化的 HibernateTransactionManager 会确保:与往常一样,一图胜千言(不过请注意,代理和真实服务之间的流程在这被高度抽象和简化了)。
理解 Spring 事务管理后,你应该对 Spring 框架是如何处理事务,以及如何应用于其他 Spring 类库(例如 Spring Boot 或 Spring WebMVC)有了一个很好的了解。最大的收获应是:最终使用哪种框架都无关紧要,这一切可以映射到 JDBC 的基础概念上。正确理解它们(记住:getConnection(),setAutocommit(false),commit()),在以后碰到复杂的企业级项目的使用,你能更容易抓住本质。
到目前为止,你已经对 Spring 事务管理有了全面的了解,希望你在实践中能够灵活运用这些知识,解决实际项目中的事务问题。感谢阅读。
Springä¸BeanFactoryä¸FactoryBeançä½ç¨ä¸åºå«
Spring Frameworkï¼ä»å¹´å¤å¤©ä½ å¯è½å·²ç»å¬è§å¾å¤ç议论ãå¨æ¬æä¸,æå°è¯å¾è§£éSpringè½å®æä»ä¹ï¼åææä¹ä¼è®¤ä¸ºå®è½å¸®å©ä½ å¼åJ2EEåºç¨ç¨åºã å¦ä¸frameworkï¼ ä½ å¯è½æ£å¨æ³âä¸è¿æ¯å¦å¤ä¸ä¸ªçframeworkâãå½å·²ç»æ许å¤å¼æ¾æºä»£ç (åä¸æ) J2EE frameworkæ¶ï¼ä¸ºä»ä¹ä½ åºè¯¥è´¹å¿è¯»è¿ç¯æç« ,æä¸è½½Spring Frameworkï¼ æç¸ä¿¡Springæ¯ç¬ç¹ç,å 为è¥å¹²ä¸ªåå : . å®å®ä½çé¢åæ¯è®¸å¤å ¶ä»æµè¡çframework没æçãSpringå ³æ³¨æä¾ä¸ç§æ¹æ³ç®¡çä½ çä¸å¡å¯¹è±¡ã . Springæ¯å ¨é¢çå模ååçãSpringæåå±çä½ç³»ç»æ,è¿æå³çä½ è½éæ©ä½¿ç¨å®å¤ç«çä»»ä½é¨å,å®çæ¶æä»ç¶æ¯å å¨ç¨³å®çãå æ¤ä»ä½ çå¦ä¹ ä¸ï¼ä½ å¯å¾å°æ大çä»·å¼ãä¾å¦,ä½ å¯è½éæ©ä» ä» ä½¿ç¨Springæ¥ç®ååJDBCç使ç¨,æç¨æ¥ç®¡çææçä¸å¡å¯¹è±¡ã . å®ç设计ä»åºé¨å¸®å©ä½ ç¼åæäºæµè¯ç代ç ãSpringæ¯ç¨äºæµè¯é©±å¨å·¥ç¨ççæ³çframeworkã Springå¯¹ä½ çå·¥ç¨æ¥è¯´ï¼å®ä¸éè¦ä¸ä¸ªä»¥ä¸çframeworkãSpringæ¯æ½å¨å°ä¸ç«å¼è§£å³æ¹æ¡,å®ä½äºä¸å ¸ååºç¨ç¸å ³ç大é¨ååºç¡ç»æãå®ä¹æ¶åå°å ¶ä»framework没æèèå°çå 容ã 尽管å®ä» ä» æ¯ä¸ä¸ªä»å¹´2ææå¼å§çå¼æºå·¥ç¨ï¼ä½Springæè¾é¿çåå²æ ¹åºãè¿ä¸ªå¼æºå·¥ç¨æ¯èµ·æºèªæå¨å¹´åæåºççãExpert One-on-One J2EE设计ä¸å¼åã书ä¸çåºç¡ä»£ç ãè¿æ¬ä¹¦å±ç¤ºäºSpringèåçåºç¡æ¶æãç¶è,è¿ä¸ªåºç¡æ¶æçæ¦å¿µè¦è¿½æº¯å°å¹´çæ©äºæ¶å,并ä¸åæ äºæ为ä¸ç³»åæåçåä¸å·¥ç¨å¼ååºç¡ç»æçç»éªã ä»å¹´1æï¼Springå·²ç»è½æ·äºSourceForgeä¸ãç°å¨æ个å¼å人å,å ¶ä¸6æ¯é«åº¦æå ¥ç积æååã Springçæ¶ææ§çå¥½å¤ å¨æ们è¿å ¥ç»è以åï¼è®©æ们çä¸ä¸Springå¯ä»¥ç»ä¸ä¸ªå·¥ç¨å¸¦æ¥çä¸äºå¥½å¤: . Springè½ææå°ç»ç»ä½ çä¸é´å±å¯¹è±¡,æ è®ºä½ æ¯å¦éæ©ä½¿ç¨äºEJBãå¦æä½ ä» ä» ä½¿ç¨äºStrutsæå ¶ä»çå å«äºJ2EEç¹æAPIsçframeworkï¼ä½ ä¼åç°Springå ³æ³¨äºéçä¸çé®é¢ï¼ã . Springè½æ¶é¤å¨è®¸å¤å·¥ç¨ä¸å¯¹Singletonçè¿å¤ä½¿ç¨ãæ ¹æ®æçç»éªï¼è¿æ¯ä¸ä¸ªä¸»è¦çé®é¢ï¼å®åå°äºç³»ç»çå¯æµè¯æ§åé¢å对象ç¹æ§ã . Springè½æ¶é¤ä½¿ç¨åç§åæ ·æ ¼å¼çå±æ§å®å¶æ件çéè¦,å¨æ´ä¸ªåºç¨åå·¥ç¨ä¸ï¼å¯éè¿ä¸ç§ä¸è´çæ¹æ³æ¥è¿è¡é ç½®ãæ¾ç»æå°è¿·æï¼ä¸ä¸ªç¹å®ç±»è¦æ¥æ¾è¿·å¹»è¬çå±æ§å ³é®åæç³»ç»å±æ§,为æ¤ä¸å¾ä¸è¯»Javadocä¹è³æºç¼ç åï¼æäºSpringï¼ä½ å¯å¾ç®åå°çå°ç±»çJavaBeanå±æ§ãåç½®æ§å¶ç使ç¨(å¨ä¸é¢è®¨è®º)帮å©å®æè¿ç§ç®åã . Springè½éè¿æ¥å£èä¸æ¯ç±»ä¿è¿å¥½çç¼ç¨ä¹ æ¯ï¼åå°ç¼ç¨ä»£ä»·å°å ä¹ä¸ºé¶ã . Spring被设计为让使ç¨å®å建çåºç¨å°½å¯è½å°çä¾èµäºä»çAPIsãå¨Springåºç¨ä¸ç大å¤æ°ä¸å¡å¯¹è±¡æ²¡æä¾èµäºSpringã . 使ç¨Springæ建çåºç¨ç¨åºæäºåå æµè¯ã . Springè½ä½¿EJBç使ç¨æ为ä¸ä¸ªå®ç°éæ©,èä¸æ¯åºç¨æ¶æçå¿ ç¶éæ©ãä½ è½éæ©ç¨POJOsælocal EJBsæ¥å®ç°ä¸å¡æ¥å£ï¼å´ä¸ä¼å½±åè°ç¨ä»£ç ã . Spring帮å©ä½ 解å³è®¸å¤é®é¢èæ é使ç¨EJBãSpringè½æä¾ä¸ç§EJBçæ¿æ¢ç©ï¼å®ä»¬éäºè®¸å¤webåºç¨ãä¾å¦,Springè½ä½¿ç¨AOPæä¾å£°ææ§äºå¡èä¸éè¿ä½¿ç¨EJB容å¨ï¼å¦æä½ ä» ä» éè¦ä¸å个çæ°æ®åºæ交éï¼çè³ä¸éè¦JTAå®ç°ã . Spring为æ°æ®ååæä¾äºä¸è´çæ¡æ¶,ä¸è®ºæ¯ä½¿ç¨JDBCæO/R mapping产åï¼å¦Hibernateï¼ã Springç¡®å®ä½¿ä½ è½éè¿æç®åå¯è¡ç解å³åæ³è§£å³ä½ çé®é¢ãè¿äºç¹æ§æ¯æå¾å¤§ä»·å¼çã Springè½åä»ä¹ï¼ Springæä¾è®¸å¤åè½,å¨æ¤æå°å¿«éå°ä¾æ¬¡å±ç¤ºå ¶å个主è¦æ¹é¢ã ä»»å¡æè¿°ï¼ é¦å ,让æ们æç¡®Springèå´ã尽管Springè¦çäºè®¸å¤æ¹é¢ï¼ä½æ们已ç»ææ¸ æ¥çæ¦å¿µï¼å®ä»ä¹åºè¯¥æ¶ååä»ä¹ä¸åºè¯¥æ¶åã Springç主è¦ç®çæ¯ä½¿J2EEæç¨åä¿è¿å¥½ç¼ç¨ä¹ æ¯ã Springä¸éæ°å¼åå·²æçä¸è¥¿ãå æ¤ï¼å¨Springä¸ä½ å°åç°æ²¡ææ¥å¿è®°å½çå ,没æè¿æ¥æ± ,没æåå¸äºå¡è°åº¦ãè¿äºåæå¼æºé¡¹ç®æä¾(ä¾å¦Commons Logging ç¨æ¥åææçæ¥å¿è¾åºï¼æCommons DBCPç¨æ¥ä½æ°æ®è¿æ¥æ± ),æç±ä½ çåºç¨ç¨åºæå¡å¨æä¾ãå 为åæ ·ççåå ï¼æ们没ææä¾O/R mappingå±ï¼å¯¹æ¤ï¼å·²ææ好ç解å³åæ³å¦HibernateåJDOã Springçç®æ æ¯ä½¿å·²åå¨çææ¯æ´å æç¨ãä¾å¦,尽管æ们没æåºå±äºå¡åè°å¤çï¼ä½æ们æä¾äºä¸ä¸ªæ½è±¡å±è¦çäºJTAæä»»ä½å ¶ä»çäºå¡çç¥ã Spring没æç´æ¥åå ¶ä»çå¼æºé¡¹ç®ç«äºï¼é¤éæ们æå°æ们è½æä¾æ°çä¸äºä¸è¥¿ãä¾å¦ï¼è±¡è®¸å¤å¼å人åï¼æ们ä»æ¥æ²¡æ为Strutsé«å ´è¿ï¼å¹¶ä¸æå°å¨MVC web frameworkä¸è¿ææ¹è¿çä½å°ãå¨æäºé¢åï¼ä¾å¦è½»é级çIoC容å¨åAOPæ¡æ¶ï¼Springæç´æ¥çç«äºï¼ä½æ¯å¨è¿äºé¢åè¿æ²¡æå·²ç»è¾ä¸ºæµè¡ç解å³æ¹æ¡ã(Springå¨è¿äºåºåæ¯å¼è·¯å éã) Springä¹å¾çäºå å¨çä¸è´æ§ã ææçå¼åè é½å¨å±åæ ·ççèµæ,åºç¡æ³æ³ä¾ç¶æ¯Expert One-on-One J2EE设计ä¸å¼åçé£äºã 并ä¸æ们已ç»è½å¤ä½¿ç¨ä¸äºä¸»è¦çæ¦å¿µ,ä¾å¦åç½®æ§å¶ï¼æ¥å¤çå¤ä¸ªé¢åã Springå¨åºç¨æå¡å¨ä¹é´æ¯å¯ç§»æ¤çã å½ç¶ä¿è¯å¯ç§»æ¤æ§æ»æ¯ä¸æ¬¡ææï¼ä½æ¯æ们é¿å ä»»ä½ç¹å®å¹³å°æéæ åå,并ä¸æ¯æå¨WebLogicï¼Tomcatï¼Resinï¼JBossï¼WebSphereåå ¶ä»çåºç¨æå¡å¨ä¸çç¨æ·ã åç½®æ§å¶å®¹å¨ Springçè®¾è®¡æ ¸å¿æ¯ org.springframework.beans å , 为ä¸JavaBeansä¸èµ·å·¥ä½è设计ã è¿ä¸ªå ä¸è¬ä¸ç´æ¥è¢«ç¨æ·ä½¿ç¨, ä½ä½ä¸ºåºç¡ä¸ºæ´å¤çå ¶ä»åè½æå¡. ä¸ä¸ä¸ªè¾é«å±é¢çæ½è±¡æ¯"Bean Factory"ã Spring bean factory æ¯ä¸ä¸ªæ®éçFactoryï¼å®ä½¿å¯¹è±¡è½å¤æå称è·åï¼å¹¶ä¸è½ç®¡ç对象ä¹é´çå ³ç³»ã Bean factories æ¯æ两ç§å¯¹è±¡æ¨¡å¼: . Singletonï¼å¨æ¤æ¨¡å¼ä¸ï¼æä¸ä¸ªå ·æç¹å®å称çå ±äº«å¯¹è±¡å®ä¾ï¼å®å¨æ¥æ¾æ¶è¢«è·åãè¿æ¯é»è®¤çï¼èä¸æ¯æ为ç»å¸¸ä½¿ç¨çãå®å¯¹äºæ ç¶æ对象æ¯ä¸ç§çæ³ç模å¼ã .Prototypeï¼å¨æ¤æ¨¡å¼ä¸ï¼æ¯æ¬¡è·åå°å建ä¸ä¸ªç¬ç«ç对象ãä¾å¦ï¼è¿å¯ä»¥è¢«ç¨äºå 许ç¨æ·æ¥æä»ä»¬èªå·±ç对象ã ç±äº org.springframwork.beans.factory.BeanFactoryæ¯ä¸ä¸ªç®åçæ¥å£ï¼å®è½è¢«ä¸ºäºåºå±åå¨æ¹æ³èå®ç°ãä½ è½å¤æ¹ä¾¿å°å®ç°ä½ èªå·±çBeanFactoryï¼å°½ç®¡å¾å°ç¨æ·éè¦ãæ为常ç¨çå®ä¹æ¯ï¼ .XmlBeanFactoryï¼ å¯è§£æç®åç´è§çå®ä¹ç±»åå½å对象å±æ§çXMLç»æã æ们æä¾äºä¸ä¸ªDTDæ¥ä½¿ç¼åæ´å®¹æã .ListableBeanFactoryImplï¼å¯æä¾è§£æåæ¾å¨å±æ§æ件ä¸çbeanå®ä¹ï¼åå¯éè¿ç¼ç¨å建BeanFactoriesã æ¯ä¸ªbeanå®ä¹å¯è½æ¯ä¸ä¸ªPOJO(éè¿ç±»ååJavaBeanåå§å±æ§å®ä¹)ï¼ææ¯ä¸ä¸ªFactoryBeanãFactoryBeanæ¥å£æ·»å äºä¸ä¸ªé´æ¥å±ãé常ï¼è¿ç¨äºä½¿ç¨AOPæå ¶ä»æ¹æ³æ¥å建代ç对象ï¼ä¾å¦ï¼æ·»å äºå£°ææ§äºå¡ç®¡çç代çã(è¿å¨æ¦å¿µä¸åEJB侦å¬ç¸ä¼¼ï¼ä½å¨å®è·µä¸å®ç°æ´ç®åã) BeanFactoriesè½å¨ä¸ä¸ªå±æ¬¡ç»æä¸å¯éæ©æ§çåä¸ï¼æ ¹æ®æ¥èªç¥å ç继æ¿å®ä¹ãè¿ä½¿å¨æ´ä¸ªåºç¨ä¸å ¬å ±é ç½®çå ±äº«æ为å¯è½ï¼è½ç¶ä¸ªå«èµæºï¼å¦controller servletsï¼ä¹æ¥æä»ä»¬èªå·±çç¬ç«ç对象éåã è¿ç§ä½¿ç¨JavaBeansçå¨æºå¨ç第åç« ä¸ææè¿°ï¼å¨TheServerSideç½ç«ä¸çæå è´¹çPDF(). éè¿BeanFactoryæ¦å¿µï¼Springæ为ä¸ä¸ªåç½®æ§å¶ç容å¨ã(æé常ä¸å欢containerè¿ä¸ªæ¯è¯ï¼å 为å®ä½¿äººèæ³å°éé级容å¨ï¼å¦EJB容å¨ãSpringçBeanFactoryæ¯ä¸ä¸ªå¯éè¿ä¸è¡ä»£ç å建ç容å¨ï¼å¹¶ä¸ä¸éè¦ç¹æ®çé¨ç½²æ¥éª¤ã) ä½äºåç½®æ§å¶èåçæ¦å¿µæ¯å¨Hollywoodååä¸ç»å¸¸è¡¨è¿°ï¼"Donât call me, Iâll call you." IoCå°æ§å¶èè´£æ¬è¿äºæ¡æ¶ä¸ï¼å¹¶è±ç¦»åºç¨ä»£ç ãæ¶åå°é ç½®çå°æ¹ï¼æææ¯è¯´å¨ä¼ ç»ç容å¨ä½ç³»ç»æä¸ï¼å¦EJBï¼ä¸ä¸ªç»ä»¶å¯ä»¥è°ç¨å®¹å¨å¹¶é®âæéè¦å®ç»æåå·¥ä½ç对象Xå¨åªé?âï¼ä½¿ç¨IoC容å¨ååªéæåºç»ä»¶éè¦X对象ï¼å¨è¿è¡æ¶å®¹å¨ä¼æä¾ç»å®ã容å¨åºäºæ¹æ³åä½åºè¿ç§è¯´æï¼æå¯è½æ ¹æ®é ç½®æ°æ®å¦XMLã åç½®æ§å¶çå 个éè¦å¥½å¤ãå¦ï¼ . å 为ç»ä»¶ä¸éè¦å¨è¿è¡æ¶é´å¯»æ¾åä½è ï¼æ以ä»ä»¬å¯ä»¥æ´ç®åçç¼ååç»´æ¤ãå¨SpringçIoCçæ¬éï¼ç»ä»¶éè¿æ´é²JavaBeançsetteræ¹æ³è¡¨è¾¾ä»ä»¬ä¾èµçå ¶ä»ç»ä»¶ãè¿ç¸å½äºEJBéè¿JNDIæ¥æ¥æ¾ï¼EJBæ¥æ¾éè¦å¼å人åç¼å代ç ã . åæ ·åå ï¼åºç¨ä»£ç æ´å®¹ææµè¯ãJavaBeanå±æ§æ¯ç®åçï¼Javaæ ¸å¿çï¼å¹¶ä¸å®¹ææµè¯ï¼ä» ç¼åä¸ä¸ªå å«èªèº«çJunitæµè¯æ¹æ³ç¨æ¥å建对象å设置ç¸å ³å±æ§å³å¯ã . ä¸ä¸ªå¥½çIoCå®ç°éèäºå¼ºç±»åãå¦æä½ ä½¿ç¨ä¸ä¸ªæ®éçfactoryæ¥å¯»æ¾åä½è ï¼ä½ å¿ é¡»éè¿ç±»å转æ¢å°è¿åç»æ转å为æ³è¦çç±»åãè¿ä¸æ¯ä¸ä¸ªä¸»è¦é®é¢ï¼ä½æ¯ä¸é è§ã使ç¨IoCï¼ä½ å¨ä½ ç代ç ä¸è¡¨è¾¾å¼ºç±»åä¾èµï¼æ¡æ¶å°è´è´£ç±»å转æ¢ãè¿æå³çå¨æ¡æ¶é ç½®åºç¨æ¶ï¼ç±»åä¸å¹é å°å¯¼è´é误ï¼å¨ä½ ç代ç ä¸ï¼ä½ æ éæ å¿ç±»å转æ¢å¼å¸¸ã . 大é¨åä¸å¡å¯¹è±¡ä¸ä¾èµäºIoC容å¨çAPIsãè¿ä½¿å¾å¾å®¹æ使ç¨éçä¸æ¥ç代ç ï¼ä¸å¾å®¹æç使ç¨å¯¹è±¡æ 论å¨å®¹å¨å æä¸å¨å®¹å¨å ãä¾å¦ï¼Springç¨æ·ç»å¸¸é ç½®Jakarta Commons DBCPæ°æ®æºä¸ºä¸ä¸ªSpring beanï¼ä¸éè¦äºä»»ä½å®å¶ä»£ç å»åè¿ä»¶äºãæ们说ä¸ä¸ªIoC容å¨ä¸æ¯ä¾µå ¥æ§çï¼ä½¿ç¨å®å¹¶ä¸ä¼ä½¿ä½ ç代ç ä¾èµäºå®çAPIsãä»»ä½JavaBenaå¨Spring bean factoryä¸é½è½æ为ä¸ä¸ªç»ä»¶ã æååºè¯¥å¼ºè°çæ¯ï¼IoC ä¸åäºä¼ ç»ç容å¨çä½ç³»ç»æ( å¦EJB), åºç¨ä»£ç æå°ç¨åº¦çä¾é äºå®¹å¨ãè¿æå³çä½ çä¸å¡å¯¹è±¡å¯ä»¥æ½å¨ç被è¿è¡å¨ä¸åçIoC æ¡æ¶ä¸-æè å¨ä»»ä½æ¡æ¶ä¹å¤-ä¸éè¦ä»»ä½ä»£ç æ¹ã 以æçç»éªåä½ä¸ºSpringç¨æ·ï¼è¿å强è°IoCç»åºç¨ä»£ç 带æ¥ç好å¤æ¯ä¸å®¹æçã IoCä¸æ¯ä¸ä¸ªæ°æ¦å¿µï¼ä½æ¯å®å¨J2EEå¢ä½éé¢ååå°è¾¾é»éæ¶é´ã æä¸äºå¯ä¾éæ©çIoC 容å¨: notably, Apache Avalon, PicoContainer å HiveMind. Avalon ä¸ä¼æ为ç¹å«æµè¡çï¼å°½ç®¡å®å¾å¼ºå¤§èä¸æå¾é¿çåå²ãAvalonæ¯ç¸å½çéé级åå¤æçï¼å¹¶ä¸çèµ·æ¥æ¯æ°çIoC解å³æ¹æ¡æ´å ·ä¾µå ¥æ§ã PicoContaineræ¯ä¸ä¸ªè½»é级èä¸æ´å¼ºè°éè¿æé å¨è¡¨è¾¾ä¾èµæ§èä¸æ¯JavaBean å±æ§ã
springçç»ä»¶åä½ç¨(springclouç»ä»¶)
ç®è¦è¯´æspringçä¸¤ä¸ªæ ¸å¿åè½åå ¶ä½ç¨
springæ¡æ¶æ¯ä¸ä¸ªè½»é级çå¼æºä»ä¼æ¡æ¶ï¼æ¯ä¸ä¸ªIOCåAOP容å¨ãå®æ¯ä½ä¾µå ¥å¼è®¾è®¡ï¼ç¬ç«äºåç§åºç¨æå¡å¨ï¼
ä¾èµæ³¨å ¥çç¹ç¹å°ç»ä»¶å ³ç³»éæåï¼éä½è¦å度
æ§å¶å转ï¼IOCï¼ï¼ç¨æ¥éä½ç¨åºä»£ç ä¹é´çè¦å度ï¼ä½¿æ´ä¸ªç¨åºä½ç³»ç»ææ´å çµæ´»ï¼åæ¶å°ç±»çå建åä¾èµå ³ç³»åå¨é ç½®æ件éï¼ç±é ç½®æä»¶æ³¨å ¥ï¼è¾¾å°æ¾è¦åçææã
DIï¼ä¾èµæ³¨å ¥ï¼
设å¼æ³¨å ¥ï¼åºå±å®ç°setæ¹æ³èµå¼ã
使ç¨æé å¨æ³¨å ¥ï¼ç½©å³åºå±å®ç°æé æ¹æ³æ³¨å ¥ï¼æ ¹æ®beanä¸çåæ°ç±»åååæ°æ°éï¼å¯»æ¾å¯¹åºçæé æ¹æ³ã
èªå¨è£ é ï¼ä¸è½èªå¨è£ é æè°çç®åç±»åå æ¬åºæ¬ç±»åï¼å符串åéåç±»é常ç¨æ¥èªå¨è£ é 对象
æç §å称æ¥èªå¨è£ é åºå±å®ç°æ¯setæ¹æ³
æç §ç±»åæ¥èªå¨è£ é åºå±å®ç°æ¯setæ¹æ³
2.é¢ååé¢ç¼ç¨ï¼AOPï¼
æ主è¦çä½ç¨ï¼å¯ä»¥å¨ä¸ä¿®æ¹æºä»£ç çæ åµä¸ï¼ç»ç®æ æ¹æ³å¨ææ·»å åè½
ä¸å¡é»è¾å°±ä¸å¿çå¤çå®é éæ±ï¼éç¨çå¢å¼ºåè½ç¬ç«åºæ¥ãå°å®å ¨äºå¡çç¨åºé»è¾ç¸å¯¹ç¬ç«çåè½æ½ååºæ¥ï¼å©ç¨Springçé ç½®æ件å°è¿äºåè½æè¿å»ï¼å®ç°äºæç §åé¢ç¼ç¨ï¼æé«äºå¤ç¨æ§ã
åç§å¢å¼ºæ¹å¼ï¼
åç½®å¢å¼ºï¼å¨æ ¸å¿åè½ä¹åæ§è¡çé¢å¤åè½
åç½®å¢å¼ºï¼å¨æ ¸ç©ææ å¿åè½ä¹åæ§è¡çé¢å¤åè½
å¼å¸¸å¢å¼ºï¼å¨æ ¸å¿åè½åçå¼å¸¸æ¶æ§è¡çé¢å¤åè½
ç¯ç»å¢å¼ºï¼å¨æ ¸å¿åè½ä¹å以åä¹åæ§è¡çé¢å¤åè½
springå å«åªäºç»ä»¶
Springæ¡æ¶æ¯ä¸ä¸ªåå±æ¶æï¼ç±7个å®ä¹è¯å¥½ç模åç»æè¢å¤ãSpring模åæ建å¨æ ¸å¿å®¹å¨ä¹ä¸ï¼æ ¸å¿å®¹å¨ç«å®´å®ä¹äºå建ãé ç½®å管çbeançæ¹å¼ï¼ç»æSpringæ¡æ¶çæ¯ä¸ªæ¨¡åï¼æç»ä»¶ï¼é½å¯ä»¥åç¬åå纤æ¹å¨ï¼æè ä¸å ¶ä»ä¸ä¸ªæå¤ä¸ªæ¨¡åèåå®ç°ã
SpringMVC主è¦ç»ä»¶è¯´æ1ãå端æ§å¶å¨DispatcherServletï¼ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾ãæ ¸å¿ãï¼
DispatcherServletæ¯SpringMVCçå ¥å£å½æ°ãæ¥æ¶è¯·æ±ï¼ååºç»æï¼ç¸å½äºè½¬åå¨ç¢§ç®ï¼ä¸å¤®å¤çå¨ãæäºDispatcherServletï¼å¯ä»¥å¤§å¤§åå°å ¶å®ç»ä»¶ä¹é´çè¦å度ã
ç¨æ·è¯·æ±å°è¾¾å端æ§å¶å¨ï¼å°±ç¸å½äºmvc模å¼ä¸çcï¼DispatcherServletæ¯æ´ä¸ªæµç¨æ§å¶çä¸å¿ï¼ç±å®è°ç¨å ¶å®ç»ä»¶æ¥å¤çç¨æ·ç请æ±ã
2ãå¤çå¨æ å°å¨HandlerMapping(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
HandlerMappingè´è´£æ ¹æ®ç¨æ·è¯·æ±ï¼URLï¼ï¼æ¾å°ç¸åºçHandlerå³å¤çå¨ï¼Controllerï¼ï¼SpringMVCæä¾äºä¸åæ å°å¨å®ç°çä¸åæ å°æ¹å¼ï¼ä¾å¦ï¼é ç½®æ件æ¹å¼ï¼å®ç°æ¥å£æ¹å¼ï¼æ³¨è§£æ¹å¼çã
3ãå¤çå¨éé å¨HandlerAdapter(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
æç §ç¹å®è§åï¼HandlerAdapterè¦æ±çè§åï¼å»æ§è¡Handlerï¼éè¿HandlerAdapter对å¤çå¨è¿è¡æ§è¡ï¼è¿æ¯éé å¨æ¨¡å¼çåºç¨ï¼éè¿æ©å±éé å¨å¯ä»¥å¯¹æ´å¤ç±»åçå¤çå¨è¿è¡å¤çã
4ãå¤çå¨Handler(éè¦å·¥ç¨å¸å¼å)
Handleræ¯ç»§DispatcherServletå端æ§å¶å¨çå端æ§å¶å¨ï¼å¨DispatcherServletçæ§å¶ä¸ï¼Handlerå¯¹å ·ä½çç¨æ·è¯·æ±è¿è¡å¤çãç±äºHandleræ¶åå°å ·ä½çç¨æ·ä¸å¡è¯·æ±ï¼æ以ä¸è¬æ åµä¸éè¦å·¥ç¨å¸æ ¹æ®ä¸å¡éæ±æ¥å¼åHandlerã
5ãè§å¾è§£æå¨ViewResolver(ä¸éè¦å¼åï¼ç±æ¡æ¶æä¾)
ä½ç¨ï¼è¿è¡è§å¾è§£æï¼æ ¹æ®é»è¾è§å¾å解ææçæ£çè§å¾ï¼Viewï¼ï¼ViewResolverè´è´£å°å¤çç»æçæViewè§å¾ãé¦å ï¼æ ¹æ®é»è¾è§å¾å解ææç©çè§å¾åï¼å³å ·ä½ç页é¢å°åï¼ï¼åçæViewè§å¾å¯¹è±¡ï¼æå对Viewè¿è¡æ¸²æï¼å°å¤çç»æéè¿é¡µé¢å±ç¤ºç»ç¨æ·ã
SpringMVCæ¡æ¶æä¾äºå¾å¤çViewè§å¾ç±»åï¼å æ¬ï¼jstlViewãfreemarkerViewãpdfViewçãä¸è¬æ åµä¸ï¼éè¦éè¿é¡µé¢æ ç¾æ页æ¸é®é¢æ¨¡çææ¯ï¼å°æ¨¡åæ°æ®éè¿é¡µé¢å±ç¤ºç»ç¨æ·ï¼è¿éè¦ç±å·¥ç¨å¸æ ¹æ®ä¸æ §å·§ä¸å¡éæ±å¼åå ·ä½ç页é¢ã
6ãè§å¾View(éè¦å·¥ç¨å¸å¼å)
Viewæ¯ä¸ä¸ªæ¥å£ï¼å®ç°ç±»æå¯ä»¥æ¯æä¸åçViewç±»åï¼jspãfreemarkerãpdf...ï¼
æ»ç»ï¼å¤çå¨Handlerï¼ä¹å°±æ¯å¹³å¸¸è¯´çControlleræ§å¶å¨ï¼ä»¥åè§å¾å±Viewï¼é½æ¯éè¦èªè¡å¼åçãå ¶ä»çä¸äºç»ä»¶ï¼å¦ï¼å端æ§å¶å¨DispatcherServletãå¤çå¨æ å°å¨HandlerMappingãå¤çå¨éé å¨HandlerAdapterçé½æ¯ç±æ¡æ¶æä¾ã
spring主è¦çä½ç¨ï¼Springæ¡æ¶æ¯ä¸ºäºè§£å³ä¼ä¸åºç¨å¼åçå¤ææ§èå建çã
Springçç¨éä¸ä» ä» éäºæå¡å¨ç«¯çå¼åãä»ç®åæ§ãå¯æµè¯æ§åæ¾è¦åæ§è§åº¦èè¨ï¼ç»å¤§é¨åJavaåºç¨é½å¯ä»¥ä»Springä¸åçã使ç¨åºæ¬çJavaBean代æ¿EJBï¼å¹¶æä¾äºæ´å¤çä¼ä¸åºç¨åè½ã
æ©å±èµæ
ä¼ç¹
1ãJAVAEEåºè¯¥æ´å 容æ使ç¨ã
2ãé¢å对象ç设计æ¯ä»»ä½å®ç°ææ¯ï¼æ¯å¦JAVAEEï¼é½éè¦ã
3ãé¢åæ¥å£ç¼ç¨ï¼èä¸æ¯é对类ç¼ç¨ãSpringå°ä½¿ç¨æ¥å£çå¤æ度éä½å°é¶ãï¼é¢åæ¥å£ç¼ç¨æåªäºå¤æ度ï¼
4ã代ç åºè¯¥æäºæµè¯ãSpringæ¡æ¶ä¼å¸®å©ä½ ï¼ä½¿ä»£ç çæµè¯å¤è¡¡æ´å ç®åã
5ãJavaBeanæä¾äºåºç¨ç¨åºé ç½®çæ好æ¹æ³ã
6ãå¨Javaä¸ï¼å·²æ£æ¥å¼å¸¸ï¼Checkedexceptionï¼è¢«è¿åº¦ä½¿ç¨ãæ¡æ¶ä¸åºè¯¥è¿«ä½¿ä½ ææ碧è·ä¸æè´ºåè½æ¢å¤çå¼å¸¸ã
åèèµææ¥æºï¼ç¾åº¦ç¾ç§-springæ¡æ¶