`
klyuan
  • 浏览: 182200 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

让Spring架构减化事务配置

    博客分类:
  • java
阅读更多
让Spring架构减化事务配置
注:原创文章,本文曾发表于it168
Spring颠覆了以前的编程模式,引入了IOC等全新的概念,广受大家的喜爱。目前大多数j2ee项目都已经采用Spring框架。Spring最大的问题是太多的配置文件,使得你不仅需要维护程序代码,还需要额外去维护相关的配置文件。最典型的就是事务配置(注:这里的“事务配置”都指“声明式事务配置”),在Spring中进行事务配置除了定义对象自身的bean外,还需要定义一个进行事务代理的bean.如果你有n个类需要引入事务,那么你就必须定义2n个bean。维护这些bean的代价是十分昂贵的,所以必须要对事务配置进行减化。如果你是基于Spring进行架构设计,那么作为一个好的架构设计师,应该把一些公共的方面进行简化,让项目的开发人员只关心项目的业务逻辑,而不要花费太多的精力去关心业务逻辑之外的太多东西。所以作为一个好的架构就应该把事务管理进行简化,让程序员花在编程之外的工作最小化。
1. Spring声明式事务配置的几种方法
在Spring中进行事务控制首先要选择适当的事务管理器,其次为程序选择划分事务的策略。如果只有单个事务性资源,可以从“单一资源”的PlatformTransactionManger实现当中选择一个,这些实现有:DataSourceTransactionManager,HibernateTransactionManager, JdoTransactionManager,PersistenceBrokerTransactionManager和JmsTransactionManager。根据你所采用的数据库持久化技术选择。如果你的项目运行于支持JTA的服务器,那么将选择JtaTransactionManger,将会支持多资源事务。
下表将为你选择适当的事务管理器提供参考。
技术 事务管理器 内建的事务支持
JDBC DataSurceTransactionManagerJtaTransactionManager JdbcTemplate和org.springframework.jdbc.object包中的所有类
IBATIS DataSourceTransactionManagerJtaTransactionManager SqlMapClientTemplate和SqlClientTemplate
Hibernate HibernateTransactionManagerJtaTransactionManager HibernateTemplate和HibernateInterceptor
JDO JdoTransactionManagerJtaTransactionManager JdoTemplate和JdoInterceptor
ApacheOJB PersistenceBrokerTransactionManagerJtaTransactionManager PersistenceBrokerTemplate
JMS JmsTransactionManager JmsTemplate

在划分事务时,我们需要进行事务定义,也就是配置事务的属性。事务的属性有传播行业,隔离级别,超时值及只读标志。TransactionAttribute接口指定哪些异常将导致一个回滚,哪些应该一次性提交。

(1) 使用ProxyFactoryBean 和TransactionInterceptor

<!--定义本地数据源-->

<bean id="dataSource" name="dataSource" class="org.apache.commons.dbcp.BasicDataSource"           destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>


<!-- !定义单个jdbc数据源的事务管理器-->
<bean id="transactionManager"               class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

   <!—定义拦截器-->
<bean id="transactionInterceptor"
      class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager">
    <ref bean="transactionManager"/>
    </property>
        <property name="transactionAttributes">
            <props>
                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
            </props>
        </property>
    </bean>

<!—定义业务对象-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService.target"
      class="com.prs.application.ehld.sample.biz.service.impl.SampleServiceImpl">
<property name="userInfoDAO"
   ref="com.prs.application.ehld.sample.integration.dao.userInfoDAO">
</property>
</bean>

<!—定义业务对象的事务代理对象-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService" class="org.springframeword.aop.framework.ProxyFacgtoryBean">
<property name="target"
   ref="com.prs.application.ehld.sample.biz.service.sampleService.target">
</property>
<property name="interceptorNames">
   <value>transactionInterceptor</value>
</property>
</bean>

通过ProxyFacgtoryBean和TransactionInterceptor组合使用,可以对事务进行更多的控制。所有需要事务控制的对象可以共享一个transactionInterceptor的事务属性。

(2) 使用TransactionProxyFactoryBean

<!—定义业务对象-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService.target"
      class="com.prs.application.ehld.sample.biz.service.impl.SampleServiceImpl">
<property name="userInfoDAO"
   ref="com.prs.application.ehld.sample.integration.dao.userInfoDAO">
</property>
</bean>

    <!—定义业务对象的事务代理对象-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
          abstract="true">
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
<property name="target"
          ref="com.prs.application.ehld.sample.biz.service.sampleService.target" />
        <property name="transactionAttributes">
            <props>
                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
            </props>
        </property>
    </bean>

使用TransactionProxyFactoryBean需要为每一个代理对象都去定义自己的事务属性。

(3) 使用TransactionProxyFactoryBean及abstract属性来简化配置
这种方工也是目前使用得最多的一种声明式事务配置方法


<!--事务控制代理抽象定义 -->
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        abstract="true">
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
            </props>
        </property>
    </bean>

<!—定义业务对象-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService.target"
      class="com.prs.application.ehld.sample.biz.service.impl.SampleServiceImpl">
<property name="userInfoDAO"
   ref="com.prs.application.ehld.sample.integration.dao.userInfoDAO">
</property>
</bean>

<!—定义业务对象的事务代理对象-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService" parent="baseTransactionProxy">
<property name="target"
   ref="com.prs.application.ehld.sample.biz.service.sampleService.target">
</property>
</bean>

使用abstract属性,可以让代理对象可以共享一个定义好的事务属性,使配置简化。

(4)使用BeanNameAutoProxyCreator
   <!—定义拦截器-->
<bean id="transactionInterceptor"
      class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager">
    <ref bean="transactionManager"/>
    </property>
        <property name="transactionAttributes">
            <props>
                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
            </props>
        </property>
    </bean>


<!—定义bean别名自动代理创建器-->
<bean id="autoProxyCreator"
  class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
   <property name="interceptorNames">
      <value>transactionInterceptor</value>
   </property>
   <property name="beanNames">
   <list>
   <idref local="com.prs.application.ehld.sample.biz.service.sampleService"/>
   </list>
   </property>
</bean>

<!—定义业务对象-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService"
      class="com.prs.application.ehld.sample.biz.service.impl.SampleServiceImpl">
<property name="userInfoDAO"
   ref="com.prs.application.ehld.sample.integration.dao.userInfoDAO">
</property>
</bean>

使用BeanNameAutoProxyCreator可以由框架来提供适当的代理,由一个transactionInterceptor统一定义事务属性,只需要把需要事务控制的bean加到beannames的列表。
  对于需要大量声明式事务的bean,BeanNameAutoProxyCreator是十分方便的。减少了代理bean的定义,还可以灵活的决定一个bean是否进行事务控制。


上面四种方法是在Spring中常见的声明式事务配置方法,其中使用TransactionProxyFactoryBean及abstract属性进行配置是最常见的简化方法。
我们暂且把需要进行事务控制的bean叫事务bean.把依赖和调用它的bean叫做业务bean。对事务bean进行代理叫做事务代理bean.

1. 使用ProxyFactoryBean 和TransactionInterceptor,可以由一个TransactionInterceptor统一定义事务属性,对于每一个事务bean都需要再定义一个事务代理bean。如果有n个事务bean,那么就需要定义和维护2n个bean。并且注入到业务bean的不是事务bean本身,而是要求用事务代理bean注入。这增加了理解的难度。
2. 使用TransactionProxyFactoryBean需要为每一个事务代理bean都定义自己的事务属性,除了需要维护2n个bean外,还需要为每一个事务代理bean定义事务属性。可以说是最麻烦的。同样需要把事务代理bean注入到业务bean,增加了理解的难度和项目的复杂度。
3. 使用TransactionProxyFactoryBean及abstract属性是对使用TransactionProxyFactoryBean的一种简单化配置,可以让所有的事务bean共享一致的事务属性定义。需要维护2n个bean,需要把事务代理bean注入到业务bean。
4. 使用BeanNameAutoProxyCreator最适合在框架中使用,只需要维护n个bean。也无需要事务代理bean。直接把事务bean注入业务bean中。但是它必须把需要事务控制的bean加到beanNames列表中。

2.类型自动代理创建器BeanClassTypeAutoProxyCreator
得于BeanNameAutoProxyCreator的启示,BeanNameAutoProxyCreator可以实现框架来实现自动代理。它只是把需要代理的bean加入beanNames属性列表。大大的简化了代理的配置,减少了代理bean的定义,使用事务bean注入业务对象,而不是代理bean注入,更合乎事务逻辑。BeanNameAutoProxyCreator仍然需要开发人员除了定义业务bean外,还需要关心事务的定义,当然已经简单了很多。如果能实现一个BeanClassTypeAutoProxyCreator,为它指定一个可以代理的ClassType列表,那么在context中所有属于ClassType和其子类的bean都自动获得代理。
实现思路:
1.BeanNameAutoProxyCreator继承了AbstractAutoProxyCreator,去实现方法:
    protected abstract Object[] getAdvicesAndAdvisorsForBean(
Class beanClass, String beanName, TargetSource customTargetSource)
在BeanNameAutoProxyCreator中的实现是判断beanName 是存在于beanNames列表,如果能找到则Object[]不对空。否则返回null。
所以BeanClassTypeAutoProxyCreator也应该继承AbstractAutoProxyCreator。
getAdvicesAndAdvisorsForBean方法的实现可以参照BeanNameAutoProxyCreator方法的实现
2.BeanClassTypeAutoProxyCreator需要有一个进行代理的ClassType列表,在bean进行初始化后就在context中查找类型为ClassType列表中类型的所有beanName.从而获得一个beanNames列表。
获得beanNames列表后就可以像BeanNameAutoProxyCreator一样实现自动代理了。
3.要想获得当前context,我们可以实现ApplicationContextAware接口。让BeanClassTypeAutoProxyCreator的bean可以获得当前context.
4. 要在bean进行初始化动作,可以实现InitializingBean接口,实现afterPropertiesSet,在这个方法中在context中根据classType查找获得相关的beanName的列表。
5. 写一个空接口,里面没有任何方法。需要事务代理的类实现这个空接口。

这样,只需要把这个空接口的全类名作为BeanClassTypeAutoProxyCreator的classTypes参数值,然后所有需要代理的类都去实现这个接口就可以自动获得代理了。无再需要任何配置。这样就可以让程序员专心于业务逻辑的开发,而无需要去关心事务控制方法,就像是没有使用事务一样。


完整的实现类如下:
BeanClassTypeAutoProxyCreator.java
/**
* 根据类型自动代理Creator
*
* @author yuanguangdong date: Jul 13, 2004
*/
public class BeanClassTypeAutoProxyCreator extends AbstractAutoProxyCreator
implements ApplicationContextAware, InitializingBean {

/** Logger that is available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());

/** ApplicationContext this object runs in */
private ApplicationContext applicationContext;

/** MessageSourceAccessor for easy message access */
private MessageSourceAccessor messageSourceAccessor;
   
/**被代理的bean别名列表**/
private List beanNames;
   
/**被代理的classType列表**/
private List classTypes;


//---------------------------------------------------------
//实现AbstractAutoProxyCreator的抽像方法
//---------------------------------------------------------
/**
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean(java.lang.Class,
*      java.lang.String, org.springframework.aop.TargetSource)
*/
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass,
String beanName, TargetSource targetSource) throws BeansException {
if (this.beanNames != null) {
if (this.beanNames.contains(beanName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}
return DO_NOT_PROXY;
}


//-------------------------------------------------------
//实现ApplicationContextAware接口方法
//-------------------------------------------------------
/**
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext context)
throws BeansException {
if (context == null && !isContextRequired()) {
// Reset internal context state.
this.applicationContext = null;
this.messageSourceAccessor = null;
} else if (this.applicationContext == null) {
// Initialize with passed-in context.
if (!requiredContextClass().isInstance(context)) {
throw new ApplicationContextException(
"Invalid application context: needs to be of type ["
+ requiredContextClass().getName() + "]");
}
this.applicationContext = context;
this.messageSourceAccessor = new MessageSourceAccessor(context);
initApplicationContext();
} else {
// Ignore reinitialization if same context passed in.
if (this.applicationContext != context) {
throw new ApplicationContextException(
"Cannot reinitialize with different application context: current one is ["
+ this.applicationContext
+ "], passed-in one is [" + context + "]");
}
}
}

/**
* Determine whether this application object needs to run in an
* ApplicationContext.
* <p>
* Default is "false". Can be overridden to enforce running in a context
* (i.e. to throw IllegalStateException on accessors if outside a context).
*
* @see #getApplicationContext
* @see #getMessageSourceAccessor
*/
protected boolean isContextRequired() {
return true;
}

/**
* Determine the context class that any context passed to
* <code>setApplicationContext</code> must be an instance of. Can be
* overridden in subclasses.
*
* @see #setApplicationContext
*/
protected Class requiredContextClass() {
return ApplicationContext.class;
}

/**
* Return the ApplicationContext instance used by this object.
*/
public final ApplicationContext getApplicationContext()
throws IllegalStateException {
if (this.applicationContext == null && isContextRequired()) {
throw new IllegalStateException(
"ApplicationObjectSupport instance [" + this
+ "] does not run in an ApplicationContext");
}
return applicationContext;
}

/**
* Return a MessageSourceAccessor for the application context used by this
* object, for easy message access.
*
* @throws IllegalStateException
*             if not running in an ApplicationContext
*/
protected final MessageSourceAccessor getMessageSourceAccessor()
throws IllegalStateException {
if (this.messageSourceAccessor == null && isContextRequired()) {
throw new IllegalStateException(
"ApplicationObjectSupport instance [" + this
+ "] does not run in an ApplicationContext");
}
return this.messageSourceAccessor;
}

public void setClassTypes(String[] classTypes) {
this.classTypes = Arrays.asList(classTypes);

}

/**
* Subclasses can override this for custom initialization behavior. Gets
* called by <code>setApplicationContext</code> after setting the context
* instance.
* <p>
* Note: Does </i>not</i> get called on reinitialization of the context but
* rather just on first initialization of this object's context reference.
*
* @throws ApplicationContextException
*             in case of initialization errors
* @throws BeansException
*             if thrown by ApplicationContext methods
* @see #setApplicationContext
*/
protected void initApplicationContext() throws BeansException {

}


//-----------------------------------
//实现InitializingBean接口方法
//-----------------------------------

    /**
     * 查找指定classType的beanName列表
     */
private List getBeanNames(String classType) {
List beanNameList = null;
try {
String[] beanName = this.getApplicationContext()
.getBeanNamesForType(Class.forName(classType), true, false);
if (beanName != null) {
beanNameList = Arrays.asList(beanName);
}
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException("Class not found: "
+ ex.getMessage());
}

return beanNameList;
}

/**
*
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {

if (classTypes != null && !classTypes.isEmpty()) {
beanNames = new ArrayList();
for (int i = 0; i < classTypes.size(); i++) {
String classType = (String) classTypes.get(i);
List aList = getBeanNames(classType);
beanNames.addAll(aList);
}
}
if (logger.isDebugEnabled()) {
for (int i = 0; i < beanNames.size(); i++) {

logger.debug("printBean:" + (String) beanNames.get(i));

}
}

}
}

3.使用BeanClassTypeAutoProxyCreator
3.1为了使用BeanClassTypeAutoProxyCreator,将为所有需要进行代理的类定一个接口。
package com.prs.application.ehld.biz.service;
public interface BaseService {

}

3.2 让需要代理的类实现或继承这个公共接口
package com.prs.application.ehld.sample.biz.service;
public interface SampleService extends BaseService {
       public void setUserInfoDAO(UserInfoDAO userInfoDAO);
       public void insertUserInfo(UserInfoDTO userInfo) throws BusinessServiceException;
}

3.3 配置事务代理
   <!—定义拦截器-->
<bean id="transactionInterceptor"
      class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager">
    <ref bean="transactionManager"/>
    </property>
        <property name="transactionAttributes">
            <props>
                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
                <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
            </props>
        </property>
    </bean>

<!—定义类型自动代理创建器-->
<bean id="autoClassTypeProxyCreator"
class="com.prs.application.ehld.common.aotoproxy.BeanClassTypeAutoProxyCreator">
  <property name="interceptorNames">
      <value>transactionInterceptor</value>
   </property>
   <property name="classTypes">
   <list>
   <value>com.prs.application.ehld.biz.service.BaseService</value>
   </list>
   </property>
</bean>

  <!—定义事务bean-->
<bean id="com.prs.application.ehld.sample.biz.service.sampleService"
      class="com.prs.application.ehld.sample.biz.service.impl.SampleServiceImpl">
<property name="userInfoDAO"
   ref="com.prs.application.ehld.sample.integration.dao.userInfoDAO">
</property>
</bean>

效果:只需要定义BeanClassTypeAutoProxyCreator,把需要代理的类型BaseService作为classTypes的值。这样任何实现了BaseService接口的类都自动获得代理。使得程序员就像配置普通bean一样去配置一个需要事务代理的bean。使得程序员只需要去关心业务逻辑。而无需要去关注事务这些框架应该支持的事情。特别是当开发团队成员水平不一,或团队人员流动性大时,BeanClassTypeAutoProxyCreator就发挥了它的作用。一个好的架构设计应该对事务控制,异常处理,日志记录这些方面进行统一的规划和处理,才能保证系统的健壮性。
采用Spring框架进行项目开发,我们在获得它的IOC等好处,同时给我们增加了维护太多配置文件的负担。应该尽量减少bean的定义,更多采用嵌套bean定义。否则将加大项目后期的维护成本。作为一个架构设计者更是应该把通用性比较强的方面进行统一规划。
分享到:
评论
11 楼 xly_971223 2007-05-26  
cskysnew 写道
xly_971223 写道
Lucas Lee 写道
spring2里对事务的配置相当简单,不需要修改普通bean的定义,
直接按照类名、方法名进行拦截。
比如:
<aop:config>
        <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* study.*Service.*(..))"/>
    </aop:config>
    
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="load*" read-only="true"/>            
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>


注意,不需要修改被管理了事务的bean的定义。

没用过spring2,有个问题请教一下
execution(* study.*Service.*(..)) 这里的匹配的是*Service类名还是bean名?感觉像是类名
如果是类名的话 是不是可以不用在spring配置文件中配置这些service bean了?

这里的*Service是表示以“Service”结尾的所有class。使用这种配置方式可以对项目中所有按此规范命名的class进行事务管理

明白了 spring在加载这些类的时候会检查是否满足这个pointcut,如果满足则会进行增强
不知道这个pointcut能不能对bean name进行拦截
10 楼 lujh99 2007-05-26  
xly_971223 写道
没用过spring2,有个问题请教一下
execution(* study.*Service.*(..)) 这里的匹配的是*Service类名还是bean名?感觉像是类名
如果是类名的话 是不是可以不用在spring配置文件中配置这些service bean了?


不配置这些service bean当然是不行的,运行时spring创建的这些匹配到的service bean对象实际是代理对象,这样才能进行拦截进行事务管理。如果不受spring管理,那么使用时只能new xxxService(),当然没办法由spring来创建代理和事务管理了。
9 楼 cskysnew 2007-05-26  
xly_971223 写道
Lucas Lee 写道
spring2里对事务的配置相当简单,不需要修改普通bean的定义,
直接按照类名、方法名进行拦截。
比如:
<aop:config>
        <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* study.*Service.*(..))"/>
    </aop:config>
    
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="load*" read-only="true"/>            
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>


注意,不需要修改被管理了事务的bean的定义。

没用过spring2,有个问题请教一下
execution(* study.*Service.*(..)) 这里的匹配的是*Service类名还是bean名?感觉像是类名
如果是类名的话 是不是可以不用在spring配置文件中配置这些service bean了?

这里的*Service是表示以“Service”结尾的所有class。使用这种配置方式可以对项目中所有按此规范命名的class进行事务管理
8 楼 cskysnew 2007-05-26  
只要在项目的命名规范能做好,用spring2的schema进行配置还是很方便的。这是expression的一个简单配置execution(* com..*Manager.save*(..))其中:“com..”表示以com为顶级package名的所有包;“*Manager”表示以Manager结尾的类;“save*(..)”表示以save开头,任意参数的方法。
7 楼 zoujinhe 2007-05-25  
楼主:
  在使用BeanNameAutoProxyCreator时,如果Spring分成多个配置文件(parent.xml和child.xml),BeanNameAutoProxyCreator配置在parent.xml中,那么child.xml定义的bean则不能实现事物(不会产生经过代理后的对象),如何解决这一问题?
6 楼 lighter 2007-05-23  
klyuan 写道
的确这是在以spring1.0作为框架进行设计的。有点老了,呵呵

我以前也写过相关的文章:
http://www.iteye.com/topic/41645
楼主写的文章有很精粹之处,欣赏你的辛苦写文,另外,代码<code>一下
5 楼 xly_971223 2007-05-23  
Lucas Lee 写道
spring2里对事务的配置相当简单,不需要修改普通bean的定义,
直接按照类名、方法名进行拦截。
比如:
<aop:config>
        <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* study.*Service.*(..))"/>
    </aop:config>
    
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="load*" read-only="true"/>            
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>


注意,不需要修改被管理了事务的bean的定义。

没用过spring2,有个问题请教一下
execution(* study.*Service.*(..)) 这里的匹配的是*Service类名还是bean名?感觉像是类名
如果是类名的话 是不是可以不用在spring配置文件中配置这些service bean了?
4 楼 klyuan 2007-04-19  
的确这是在以spring1.0作为框架进行设计的。有点老了,呵呵
3 楼 wensky222 2007-04-19  
spring2确实简单,但是在web应用的配置上总是有一层需要自动感应(atuowiring =“true”),有点美中不足。
spring2里要是有命名空间就更好了,重名的问题就好解决了
当然现在也可以 包名+类名
2 楼 LucasLee 2007-04-19  
spring2里对事务的配置相当简单,不需要修改普通bean的定义,
直接按照类名、方法名进行拦截。
比如:
<aop:config>
        <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* study.*Service.*(..))"/>
    </aop:config>
    
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="load*" read-only="true"/>            
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>


注意,不需要修改被管理了事务的bean的定义。
1 楼 lizwjiang 2007-04-19  
你这个简化配置其实是针对spring1.x的版本,建议你看看spring2.x,可以进一步简化

相关推荐

    Spring声明式事务配置管理方法

    发布于2013-5-6项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring2.0AOP类库即可。添加方法:点击项目右键-&gt;BuildPath-&gt;Addlibrarys:打开AddLibraries对话框,然后选定...

    基于Spring Authorization Server全新适配OAuth 2.1协议的企业级微服务架构和服务能力开发平台

    2022.0.4、Spring Cloud Alibaba 2023.0.0.0、Nacos 2.3.1 等主流技术栈开发的多租户系统,遵循SpringBoot 编程思想,高度模块化和可配置化。具备服务发现、配置、熔断、限流、降级、监控、多级缓存、分布式事务、...

    精通Spring(书签)

     Spring 2.5是迄今为止完美的Java EE架构级框架,全面深入、多维度演绎Spring 2.5的各个方面,本书蕴含作者多年Java EE研发实践及经验。  凝聚Java魅力,成就开发专家  看清Java万花的本质,从复杂的表象中寻找...

    spring声明式事务管理

    3. 掌握整合spring和hibernate的持久化操作编程 4.掌握基于AOP的声明式事务编程 按照三层架构构建web项目,在业务层添加事务控制。 1.创建web project项目命名为aopweb 2.添加spring支持、hibernate支持 3.配置WEB...

    精通spring--源代码

    精通spring 源代码 对JavaEE5及Spring2.5进行了综述。包括Java EE5,步入Spring2.5,获得Spring2.5发布版和源码。启动Spring2.5使能项目  详细介绍Spring2.5核心技术。包括控制反转容器,面向切面编程  对DA0层...

    SpringColud1简易分布式

    SpringColud1简易分布式 ● cloud-config-server:配置服务器-(通过git获取配置) ● cloud-eureka-server:eureka注册服务器 ● cloud-simple-service:一个使用mybatis的数据库应用,服务端 ● cloud-simple-...

    基于Spring Cloud的进销存管理系统源码

    采用前后端分离的模式,微服务版本前端vue 后端采用Spring Boot、Spring Cloud & Alibaba。注册中心、配置中心选型Nacos,权限认证使用Redis。流量控制框架选型Sentinel,分布式事务选型Seata。 商品管理:商品类型...

    基于Spring Boot、Spring Cloud Alibaba的分布式微服务架构权限管理系统,同时提供了 Vue3 的版本

    基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构权限管理系统,同时提供了 Vue3 的版本。若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。采用前后端...

    基于Spring BootSpring Cloud & Alibaba的分布式微服务架构权限管理系统同时提供了 Vue

    基于Spring Boot、Spring Cloud & Alibaba的分布式微服务架构权限管理系统,同时提供了 Vue3 的版本。若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。采用前后端分离的模式,微服务版本前端(基于...

    spring.net中文手册在线版

    14.5.1.理解Spring.NET声明式事务管理的实现 14.5.2.第一个例子 14.5.3.Transaction特性的设置 14.5.4.通过AutoProxyCreator使用声明式事务 14.5.5.通过TransactionProxyFactoryObject使用声明式事务 14.5.6. 通过...

    springmvc+ibatis框架包,使用spring注入,事务等,包都齐全

    自己配置的springmvc+ibatis框架,自己找齐了包,不容易啊,所以上来跟大家分享一下,spring自动注入包,事务包,ibatis包,数据库连接包,都齐全的,仅局限于springmvc+ibatis,这些包不多,不少,刚够

    spring boot 全面的样例代码

    - chapter9-1-4:[Spring Cloud构建微服务架构(四)分布式配置中心](http://blog.didispace.com/springcloud4/) - chapter9-1-5:[Spring Cloud构建微服务架构(五)服务网关]...

    基于Spring Cloud+Vue的班级事务管理系统源码(毕设源码)+项目使用说明.zip

    基于Spring Cloud+Vue的班级事务管理系统源码(毕设源码)+项目使用说明.zip 【系统架构】 项目采用B/S架构,前后端通讯采用RESTful API,数据格式使用Json,认证Token格式采用JWT。 身份认证使用Spring Security ...

    SpringCloud H版+SpringCloud alibaba

    SpringCloud H版+SpringCloud alibaba构成,内容涵盖了分布式...分享了服务降级、服务熔断、服务限流、hotkey控制、分布式统一配置管理、分布式全局事务控制、RabbitMQ与Stream整合、Nacos和Nginx配置高可用集群等技术

    SpringCloud思维导图

    1.微服务架构零基础理论入门 2.从2.2.x和H版开始说起 3.关于Cloud各种组件的停更/升级/替换 4.微服务架构编码构建 ...8.Ribbon负载均衡服务调用 9.OpenFeign服务接口调用 ...21.SpringCloud Alibaba
Seata处理分布式事务

    yudao-cloud是以 ruoyi-vue-pro为基础实现的 Spring Cloud Alibaba 微服务架构.rar

    后端采用 Spring Cloud Alibaba 微服务架构,注册中心 + 配置中心 Nacos,消息队列 RocketMQ,定时任务 XXL-Job,服务保障 Sentinel,服务网关 Gateway,分布式事务 Seata 数据库可使用 MySQL、Oracle、PostgreSQL...

    用于将所有Spring xml配置转换为基于Spring java的配置的工具(高分毕设).zip

    Java SSM项目是一种使用Java语言和SSM框架(Spring + Spring MVC + MyBatis)开发的Web应用程序。SSM是一种常用的Java开发框架组合,它结合了Spring框架、Spring MVC框架和MyBatis框架的优点,能够快速构建可靠、...

    Spring攻略(第二版 中文高清版).part1

    1.1 实例化Spring IoC容器 1 1.1.1 问题 1 1.1.2 解决方案 1 1.1.3 工作原理 3 1.2 配置Spring IoC容器中的Bean 4 1.2.1 问题 4 1.2.2 解决方案 4 1.2.3 工作原理 4 1.3 调用构造程序创建Bean 14 ...

    基于Spring Boot、Spring Cloud & Alibaba的分布式微服务架构权限管理系统

    基于Spring Boot、Spring Cloud & Alibaba的分布式微服务架构权限管理系统。采用前后端分离的模式,微服务版本前端(基于 RuoYi-Vue)。后端采用Spring Boot、Spring Cloud & Alibaba。注册中心、配置中心选型Nacos,...

Global site tag (gtag.js) - Google Analytics