spring mvc原理是怎么去整合原理

Spring @Transactional工作原理 - ImportNew
| 标签: ,
本文将深入研究Spring的事务管理。主要介绍@Transactional在底层是如何工作的。之后的文章将介绍:
propagation(事务传播)和isolation(隔离性)等属性的使用
事务使用的陷阱有哪些以及如何避免
JPA和事务管理
很重要的一点是JPA本身并不提供任何类型的声明式事务管理。如果在依赖注入容器之外使用JPA,事务处理必须由开发人员编程实现。
UserTransaction utx = entityManager.getTransaction();
utx.begin();
businessLogic();
} catch(Exception ex) {
utx.rollback();
这种方式的事务管理使事务范围可以在代码中很清晰地表达出来,但它有以下缺点:
容易出现重复代码和错误
任何错误可能产生较大的影响
错误难以调试和复现
降低了代码库的可读性
如果该方法调用了其他的事务方法如何处理呢?
使用Spring @Transactional
使用Spring @Transactional,上面的代码就简化为:
@Transactional
public void businessLogic() {
... use entity manager inside a transaction ...
代码更加简洁,可读性更好,也是目前Spring中事务处理的推荐方式。
通过使用@Transactional,事务传播等很多重要方面可以自动处理。这种情况下如果businessLogic()调用了其他事务方法,该方法将根据选项确定如何加入正在运行事务。
这个强大机制的一个潜在缺点是它隐藏了底层的运行,当它不能正常工作时很难调试。
@Transactional含义
关于@Transactional,关键点之一是要考虑两个独立的概念,它们都有各自的范围和生命周期:
persistence context(持久化上下文)
database transaction(事务)
@Transactional本身定义了单个事务的范围。这个事务在persistence context的范围内。
JPA中的持久化上下文是EntityManager,内部实现使用了Hibernate Session(使用Hibernate作为持久化provider)。
持久化上下文仅仅是一个同步对象,它记录了有限集合的Java对象的状态,并且保证这些对象的变化最终持久化到数据库。
这是与单个事务非常不同的概念。一个Entity Manager可以跨越多个事务使用,而且的确是这样使用的。
EntityManager何时跨越多个事务?
最常见的情况是应用使用Open Session In View模式处理懒初始化异常时,之前的文章介绍过这种做法的。
这种情况下视图层运行的多个查询处于独立的事务中,而不是单事务的业务逻辑,但这些查询由相同的entity manager管理。
另一种情况是开发人员将持久化上下文标记为PersistenceContextType.EXTENDED,这表示它能够响应多个请求。
如何定义EntityManager和Transaction之间的关系?
这由应用开发者来选择,但是JPA Entity Manager最常用的方式是“Entity Manager per application transaction”(每个事务都有自己的实体管理器)模式。entity manager注入的常用方法是:
@PersistenceContext
private EntityM
这里默认为“Entity Manager per transaction”模式。这种模式下如果在@Transactional方法内部使用该Entity Manager,那么该方法将在单一事务中运行。
@PersistenceContext如何工作?
随之而来的问题就是@PersistenceContext如何仅在容器启动时注入entity manager,假定entity manager生命周期很短暂,而且每次请求需要多个entity manager。
答案是它不能:EntityManager是一个接口,注入到spring bean中的不是entity manager本身,而是在运行时代理具体entity manager的context aware proxy(上下文感知代理)。
通常用于代理的具体类为SharedEntityManagerInvocationHandler,借助调试器可以确认这一点。
那么@Transactional如何工作?
实现了EntityManager接口的持久化上下文代理并不是声明式事务管理的唯一部分,事实上包含三个组成部分:
EntityManager Proxy本身
事务的切面
事务管理器
看一下这三部分以及它们之间的相互作用。
事务的切面
事务的切面是一个“around(环绕)”切面,在注解的业务方法前后都可以被调用。实现切面的具体类是TransactionInterceptor。
事务的切面有两个主要职责:
在’before’时,切面提供一个调用点,来决定被调用业务方法应该在正在进行事务的范围内运行,还是开始一个新的独立事务。
在’after’时,切面需要确定事务被提交,回滚或者继续运行。
在’before’时,事务切面自身不包含任何决策逻辑,是否开始新事务的决策委派给事务管理器完成。
事务管理器
事务管理器需要解决下面两个问题:
新的Entity Manager是否应该被创建?
是否应该开始新的事务?
这些需要事务切面’before’逻辑被调用时决定。事务管理器的决策基于以下两点:
事务是否正在进行
事务方法的propagation属性(比如REQUIRES_NEW总要开始新事务)
如果事务管理器确定要创建新事务,那么将:
创建一个新的entity manager
entity manager绑定到当前线程
从数据库连接池中获取连接
将连接绑定到当前线程
使用变量将entity manager和数据库连接都绑定到当前线程。
事务运行时他们存储在线程中,当它们不再被使用时,事务管理器决定是否将他们清除。
程序的任何部分如果需要当前的entity manager和数据库连接都可以从线程中获取。
EntityManager proxy
EntityManager proxy(前面已经介绍过)就是谜题的最后一部分。当业务方法调用entityManager.persist()时,这不是由entity manager直接调用的。
而是业务方法调用代理,代理从线程获取当前的entity manager,前面介绍过事务管理器将entity manager绑定到线程。
了解了@Transactional机制的各个部分,我们来看一下实现它的常用Spring配置。
整合三个部分
如何将三个部分组合起来使事务注解可以正确地发挥作用呢?首先定义entity manager工厂。
这样就可以通过持久化上下文注解注入Entity Manager proxy。
@Configuration
public class EntityManagerFactoriesConfiguration {
@Autowired
private DataSource dataS
@Bean(name = &entityManagerFactory&)
public LocalContainerEntityManagerFactoryBean emf() {
LocalContainerEntityManagerFactoryBean emf = ...
emf.setDataSource(dataSource);
emf.setPackagesToScan(
new String[] {&your.package&});
emf.setJpaVendorAdapter(
new HibernateJpaVendorAdapter());
下一步实现配置事务管理器和在@Transactional注解的类中应用事务的切面。
@Configuration
@EnableTransactionManagement
public class TransactionManagersConfig {
@Autowired
EntityManagerF
@Autowired
private DataSource dataS
@Bean(name = &transactionManager&)
public PlatformTransactionManager transactionManager() {
JpaTransactionManager tm =
new JpaTransactionManager();
tm.setEntityManagerFactory(emf);
tm.setDataSource(dataSource);
注解@EnableTransactionManagement通知Spring,@Transactional注解的类被事务的切面包围。这样@Transactional就可以使用了。
Spring声明式事务管理机制非常强大,但它可能被误用或者容易发生配置错误。
当这个机制不能正常工作或者未达到预期运行结果等问题出现时,理解它的内部工作情况是很有帮助的。
需要记住的最重要的一点是,要考虑到两个概念:事务和持久化上下文,每个都有自己不可读的明显的生命周期。
下一篇文章将介绍事务注解的常见陷阱以及如何避免。
原文链接:
- 译文链接: [ 转载请保留原文出处、译者和译文链接。]
关于作者:
(新浪微博:)
作者分析得很详细,谢谢作者的分享。
关于ImportNew
ImportNew 专注于 Java 技术分享。于日 11:11正式上线。是的,这是一个很特别的时刻 :)
ImportNew 由两个 Java 关键字 import 和 new 组成,意指:Java 开发者学习新知识的网站。 import 可认为是学习和吸收, new 则可认为是新知识、新技术圈子和新朋友……
新浪微博:
推荐微信号
反馈建议:@
广告与商务合作QQ:
– 好的话题、有启发的回复、值得信赖的圈子
– 写了文章?看干货?去头条!
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 活跃 & 专业的翻译小组
– 国内外的精选博客文章
– UI,网页,交互和用户体验
– JavaScript, HTML5, CSS
– 专注Android技术分享
– 专注iOS技术分享
– 专注Java技术分享
– 专注Python技术分享
& 2017 ImportNew博客分类:
&&& 在我们使用spring框架的过程中,在很多时候我们会使用@async注解来异步执行某一些方法,提高系统的执行效率。今天我们来探讨下 spring 是如何完成这个功能的。
&&& spring 在扫描bean的时候会扫描方法上是否包含@async的注解,如果包含的,spring会为这个bean动态的生成一个子类,我们称之为代理类(?),代理类是继承我们所写的bean的,然后把代理类注入进来,那此时,在执行此方法的时候,会到代理类中,代理类判断了此方法需要异步执行,就不会调用父类(我们原本写的bean)的对应方法。spring自己维护了一个队列,他会把需要执行的方法,放入队列中,等待线程池去读取这个队列,完成方法的执行,从而完成了异步的功能。我们可以关注到再配置task的时候,是有参数让我们配置线程池的数量的。因为这种实现方法,所以在同一个类中的方法调用,添加@async注解是失效的!,原因是当你在同一个类中的时候,方法调用是在类体内执行的,spring无法截获这个方法调用。
&&& 那在深入一步,spring为我们提供了AOP,面向切面的功能。他的原理和异步注解的原理是类似的,spring在启动容器的时候,会扫描切面所定义的类。在这些类被注入的时候,所注入的也是代理类,当你调用这些方法的时候,本质上是调用的代理类。通过代理类再去执行父类相对应的方法,那spring只需要在调用之前和之后执行某段代码就完成了AOP的实现了!
&& 那最后我们还有一个问题,spring是如何动态的生成某一个类的子类的?代理类?
&& 生成代理类可以通过jdk 和 CGLIB 两种方式生成.具体的可以
&& 参考 1.代理类说明:
&&&&&&& 2.CGLIB和JDK代理类的区别:
这里就不详细说明了
cheng.xinwei
浏览: 44058 次
来自: 上海
终于找到这个我很疑惑的问题的答案了。之前也遇到过想在一个方法里 ...
解决了我三年后的问题
看了下源码凌乱了,楼主分析的不错有耐 ...
厉害,解决了
问题解决了,非常感谢。
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'Struts2整合Spring方法及原理
一、&&&Struts
2框架整合Spring步骤
1、&复制文件。复制struts2-spring-plugin-x-x-x.jar和spring.jar到WEB-INF/lib目录下。其中的x对应了Spring的版本号。还需要复制commons-logging.jar文件到WEB-INF/lib目录下。
2、&配置struts.objectFactory属性值。在struts.properties中设置struts.objectFactory属性值:struts.objectFactory
或者在XML文件中进行常量配置:
&constant name="struts.objectFactory" value="spring"
3、&配置Spring监听器。在web.xml文件中增加如下内容:
&listener&
&listener-class&
org.springframework.web.context.ContextLoaderListener
&/listener-class&
&/listener&
4、&Spring配置文件。默认情况下,Spring配置文件为applicationContext.xml,该文件需要保存在Web应用的WEB-INF目录下。内容示例如下所示:
&?xml version="1.0"
encoding="UTF-8"?&
&!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"&
&bean id="personManager"
class="com.acme.PersonManager"/&
开发者实际上可以使用多个Spring配置文件,在web.xml中进行下列设置,从而使Spring的ApplicationContext通过匹配所给定模式的文件来初始化对象:
&!--&用来定位Spring
XML文件的上下文配置 --&
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&
/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml
&/param-value&
&/context-param&
5、&修改Struts配置文件。Struts
2框架整合Spring框架,需要在Struts配置文件中有所改变,下面是一个示例:
&!DOCTYPE struts
"-//Apache Software Foundation//DTD Struts Configuration
"http://struts.apache.org/dtds/struts-2.0.dtd"&
file="struts-default.xml"/&
&package name="default"
extends="struts-default"&
&&&&&&&&&&
&action name="foo"
class="com.acme.Foo"&
&&&&&&&&&&&&&&
&result&foo.ftl&/result&
&&&&&&&&&&
&/package&
&package name="secure" namespace="/secure"
extends="default"&
&&&&&&&&&&
&action name="bar"
class="bar"&
&&&&&&&&&&&&&&
&result&bar.ftl&/result&
&&&&&&&&&&
&/package&
该配置文件中定义了两个Action配置:foo是一个标准的Struts
2框架Action配置,指定了Action实现类为com.acme.Foo;bar对应的class并不存在,那么框架将在Spring配置文件中查找id属性为“bar”的定义,该配置文件如下所示:
&?xml version="1.0"
encoding="UTF-8"?&
&!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"&
&bean id="bar" class="com.my.BarClass"
singleton="false"/&
二、整合原理Struts2与Spring的集成要用到Spring插件包struts2-spring-plugin-x-x-x.jar,这个包是同Struts2一起发布的。Spring插件是通过覆盖(override)Struts2的ObjectFactory来增强核心框架对象的创建。当创建一个对象的时候,它会用Struts2配置文件中的class属性去和Spring配置文件中的id属性进行关联,如果能找到,则由Spring创建,否则由Struts
2框架自身创建,然后由Spring来装配。Spring插件具体有如下几个作用:
—&允许Spring创建Action、Interceptror和Result。
—&由Struts创建的对象能够被Spring装配。
—&如果没有使用Spring
ObjectFactory,提供了2个拦截器来自动装配action。
&开发者不必在Spring中去注册action,尽管可以这么去做,通常Struts框架会自动地从action
mapping中创建action对象
struts2-spring-plugin-x-x-x.jar插件中有一个struts-plugin.xml文件,该文件内容如下所示:
&!DOCTYPE struts
"-//Apache Software Foundation//DTD Struts Configuration
"http://struts.apache.org/dtds/struts-2.0.dtd"&
&bean type="com.opensymphony.xwork2.ObjectFactory"
name="spring"
class="org.apache.struts2.spring.StrutsSpringObjectFactory"
&!--&&设置Spring对象工厂为自动
&constant name="struts.objectFactory" value="spring"
name="spring-default"&
&interceptors&
&&&&&&&&&&&
&interceptor name="autowiring"
class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/&
&&&&&&&&&&&
&interceptor name="sessionAutowiring"
class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/&
&/interceptors&
&/package&&&&
其中设置了Struts
2框架常量struts.objectFactory的值为spring,实际上,spring是org.apache.struts2.spring.StrutsSpringObjectFactory类的缩写,默认情况下所有由Struts
2框架创建的对象都是由ObjectFactory实例化的,ObjectFactory提供了与其他IoC容器如Spring、Pico等集成的方法。覆盖这个ObjectFactory的类必须继承ObjectFactory类或者它的任何子类,并且要带有一个不带参数的构造方法。在这里用org.apache.struts2.spring.StrutsSpring
ObjectFactory代替了默认的ObjectFactory。
如果Action不是使用Spring
ObjectFactory创建的话,插件提供了两个拦截器来自动装配Action,默认情况下框架使用的自动装配策略是name,也就是说框架会去Spring中寻找与Action属性名字相同的bean,可选的装配策略还有:type、auto、constructor,开发者可以通过常量struts.objectFactory.spring.autoWire来进行设置。&
2框架整合Spring后,处理用户请求的Action并不是Struts框架创建的,而是由Spring插件创建的。创建实例时,不是利用配置Action时指定的class属性值,根据bean的配置id属性,从Spring容器中获得相应的实例。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。下次自动登录
现在的位置:
& 综合 & 正文
Spring与Struts2整合原理
Spring 和Struts 2都是应用非常广泛的J2EE应用程序框架,Struts 2主要注重的是将视图层和控制层分开,但是不涉及对模型层的优化设计;而Spring除了实现Struts
2的MVC功能外,还可以利用其控制反转的思想实现对模型层的优化,从更深层次去降低应用程序各个组件的耦合程度。
1、添加ContextLoaderListener到web.xml
org.springframework.web.context.ContextLoaderListener
如果需要添加多个spring配置文件就要在web.xml加入contextConfigLocation这个context参数
contextConfigLocation
/WEB-INF/classes/applicationContext-*.xml
contextConfigLocation
classpath:beans.xml
ContextLoaderListener的作用 :
ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
在ContextLoaderListener中关联了ContextLoader这个类,所以整个加载配置过程由ContextLoader来完成。
(org.springframework.web.context.ContextLoaderListener创建出
WebApplicationContext容器对象, 并将创建出来的WebApplicationContext对象存储进了Web应用程序的application作用域中,存储时的key为 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE这个常量表示的字符串,以后在Web应用程序中就可以使用
application.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)
Spring提供的工具方法
WebApplicationContextUtils.getWebApplicationContext(application)来获得 spring容器对象
&context-param&(/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml)
&context-param&节点就是用来为这个全局对象配置参数的,这样就可以在整个项目中都能使用,spring就是通过servletConfig来读取web.xml中的路径参数来过得beans.xml等一些spring的xml文件的。用来定位Spring
XML文件的上下文配置。ContextLoaderListener使用contextConfigLocation这个ServletContext初始化参数来指定WebApplicationContext容器对象的配置文件,如果没有配置contextConfigLocation这个
ServletContext的初始化参数,ContextLoaderListener则默认使用/WEB-INF /applicationContext.xml作为配置文件。
以上是web.xml,下面是修改struts.xml
2在发布的时候在其插件包struts-2.1.2\lib中有struts2-spring-plugin-2.1.2.jar,正是它实现了Struts 2和Spring的整合。这个插件覆盖了Struts 2的ObjectFactory,所以在Struts 2创建一个对象的时候,例如Action类,它会先到Struts 2的配置文件去寻找类的名字,然后转到Spring配置文件中去查找名字找到该类。
当创建一个对象的时候,它会用Struts2 配置文件中的class属性去和Spring配置文件中的id属性进行关联,如果能找到,则由Spring创建,否则由Struts 2框架自身创建 ,然后由Spring来装配 。Spring插件具体有如下几个作用:
— 允许Spring创建Action、Interceptror和Result。
— 由Struts创建的对象能够被Spring装配。
— 如果没有使用Spring ObjectFactory,提供了2个拦截器来自动装配action 。
在这个插件包中有个struts-plugin.xml文件,它的内容如下:
&bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" /&
Make the Spring object factory the automatic default --&
&constant name="struts.objectFactory" value="spring" /&
&constant name="struts.class.reloading.watchList" value="" /&
&constant name="struts.class.reloading.acceptClasses" value="" /&
&constant name="struts.class.reloading.reloadConfig" value="false" /&
&package name="spring-default"&
&interceptors&
&interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/&
&/interceptors&
&/package&
其中设置了Struts 2框架常量struts.objectFactory的值为spring,默认情况下action是有struts2的工厂生产的.在这里把它交给了Spring生产
这里它将框架常量struts.objectFactory覆盖了,设置为”spring”,其实这里是使用了缩写,我们可以写全称:org.apache.struts2.spring.StrutsSpringObjectFactory。这个缩写的”spring”是和bean配置中的name属性相对应的。默认情况下所有由框架创建的对象都是由ObjectFactory实例化的,ObjectFactory提供了与其它IoC容器如Spring、Pico等集成的方法。覆盖这个ObjectFactory的类必须继承ObjectFactory类或者它的任何子类,并且要带有一个不带参数的构造方法。在这里我们用org.apache.struts2.spring.StrutsSpringObjectFactory代替了默认的ObjectFactory。
如果action不是使用Spring ObjectFactory创建的话,插件提供了两个拦截器来自动装配action,默认情况下框架使用的自动装配策略是name,也就是说框架会去Spring中寻找与action属性名字相同的bean,可选的装配策略还有:type、auto、constructor,我们可以通过常量struts.objectFactory.spring.autoWire来进行设置。
Struts 2框架整合Spring后,处理用户请求的Action并不是Struts框架创建的,而是由Spring插件创建的。创建实例时,不是利用配置Action时指定的class属性值,根据bean的配置id属性,从Spring容器中获得相应的实例。
注意:strut.xml中配置的action的class值,应该与spring中配置的Action
Bean id 相应。
&filter-name&f&/filter-name&
&filter-class&org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter&/filter-class&
&filter-mapping&
&filter-name&f&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&classpath:beans.xml&/param-value&
&/context-param&
&listener&
&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&
&/listener&
&&&&推荐文章:
【上篇】【下篇】博客分类:
JBPM基于Spring系统工作流平台整合2------整合原理
声明:该文系作者原创,如您用于商业用途或者论文发表,请您一定要通知作者本人同意方可引用。
前提:首先本文的整合指的范围比较大,不仅指系统和JBPM之间的整合,而是对于系统适应不同工作流产品(遵循WFMC标准)的快速整合。
工作流平台
1、IBM的Flowmark/MQ Series
2、微软的Workflow Designer for Exchange
3、JBPM-jboss
4、OsWorkFlow-opensymphony
5、普元EOS
6、协同SynchroFlow
WFMC定义的流程模型
WFMC描述的通用工作流程产品结构
工作流基本概念
工作流:工作流就是业务流程的计算机化或自动化
工作流系统:定义、创建、执行工作流的系统,通过软件定义、创建工作流并管理其执行
:是由约家成员参加的组织,基于参考模型定义了一系列的标准。参考模型用例()的形式描述了工作流系统和其他相关部分之间的关系。是制定的描述业务流程控制流()的格式规范
:业务流程管理
工作流引擎 :核心组件,负责生成流程运行时的各种实例及数据,以及监视和管理流程的运行
流程定义 :预先定义的业务逻辑,对一个流程抽象的对象化定义,工作流的流程的完整定义,包括节点和节点之间的走向等关键信息。通常以格式提供
流程实例 :业务的实际流转过程
节点:对流程中的过程环节行为的抽象对象化定义
参与者 :任务的参与者(可能是人也可能是角色或是组织等)
任务 :业务逻辑上,会呈现给参与者处理的元素
任务实例 :业务实际流转过程中,生成的需要参与者进行参与的实际内容
流转 :连接业务逻辑不同节点的桥梁,也是业务实例进行流转的依据。描述流程中从一个结点到另一个结点的状态转换过程,因此一个转向一定有一个源结点和一个目标结点
工作列表(worklist):根据实际应用的需求,需要展示给参与者的任务实例列表
使用工作流什么
通常来说,作为工作流中间件平台来说,其功能覆盖面较广,但对于整合来说,我们使用的主要如下:
、流程模型的定义和管理;
2、流程引擎的使用,通俗来说,也就是工单从一个节点到另一个节点的扭转,并且保证运行到正确的节点;
系统和JBPM整合思想
基于,以接口方式通过系统工作流中间层调用方式实现扭转。以模型中的方式调用系统接口。统一数据库,事务交由系统统一托管。
wangyisong
浏览: 218722 次
来自: 北京
[color=red][/color]为什么我的自定义组建不出 ...
auditionlsl 写道在使用Flex4时:
代码:cre ...
成功,perfect.
感谢楼主的共享,很受用
请问:我用第二种绑定了数据,BindingUtils.bind ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 spring mvc原理 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信