随笔-112  评论-73  文章-0  trackbacks-0

想在Service 层配置事务,Spring 好象是要求必须用接口,因为我没用接口时没配置成功.

一个IService 接口.声明了所有Service层公共的方法,比如save、delete 等。

public interface IService {

    public int count(FindCriteria fc);

 

    public List find(FindCriteria fc);

 

    public Serializable save(Object object) throws UnsupportedOperationException;

}

 

UserService 接口,声明UserService 的所有方法。还要 extends IService

public interface UserService extends IService {

 

    public User login(User user);

    

}

 

UserService接口的实现类.

public class UserServiceImpl implements UserService {

 

    /**

     * 登录

     *

     * @param user

     * @return 校验成功的User实例

     */

    public User login(User u) throws UnsupportedOperationException {

        // throw new UnsupportedOperationException();

        User user = (User) userDao.get(User.class, u.getId());

        log.debug("get user is " + user);

        if (user != null && user.getPassword().equals(u.getPassword()))

            return user;

        return null;

    }

 

//其他实现省略

}

完整的applicationContent.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

 

    <!-- 连接属性 -->

    <bean id="propertyConfigurer"

        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

        <property name="location" value="WEB-INF/jdbc.properties" />

    </bean>

 

    <!-- 数据源 -->

    <bean id="dataSource"

        class="org.apache.commons.dbcp.BasicDataSource">

        <property name="driverClassName" value="${jdbc.driver}" />

        <property name="url" value="${jdbc.url}" />

        <property name="username" value="${jdbc.user}" />

        <property name="password" value="${jdbc.password}" />

    </bean>

 

    <!-- hibernate sessionFactory -->

    <bean id="sessionFactory"

        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

        <property name="dataSource" ref="dataSource" />

        <property name="hibernateProperties">

            <props>

                <prop key="hibernate.dialect">

                    ${hibernate.dialect}

                </prop>

                <prop key="hibernate.show_sql">true</prop>

                <prop key="hibernate.query.substitutions">

                    true 1, false 0, yes 'Y', no 'N'

                </prop>

                <prop key="hibernate.jdbc.fetch_size">50</prop>

                <prop key="hibernate.jdbc.batch_size">25</prop>

            </props>

        </property>

        <property name="annotatedClasses">

            <list>

                <value>cn.xiangyunsoft.busniess.model.Rose</value>

                <value>cn.xiangyunsoft.busniess.model.User</value>

                <value>cn.xiangyunsoft.busniess.model.Department</value>

            </list>

        </property>

    </bean>

 

    <!-- 配置事务管理 -->

 

    <!-- 事务通知类 -->

    <bean id="profiler"

        class="cn.xiangyunsoft.busniess.service.SimpleProfiler">

        <!-- order 值可以决定通知的先后顺序 ,与后面的order的值的大小,决定了是先通知再执行,还是先执行再通知-->

        <property name="order" value="2" />

    </bean>

 

    <bean id="transactionManager"

        class="org.springframework.orm.hibernate3.HibernateTransactionManager">

        <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">

        <!-- the transactional semantics... -->

        <tx:attributes>

            <!-- get find 开头的方法是只读事务 -->

            <tx:method name="get*" read-only="true" />

            <tx:method name="find*" read-only="true" />

            <!-- 其他方法是默认 -->

            <tx:method name="*" />

        </tx:attributes>

    </tx:advice>

 

    <aop:config>

        <!-- 此处的IService 是表示对所有实现IService接口的类管理事务 -->

        <aop:pointcut id="serviceOperation"

            expression="execution(* cn.xiangyunsoft.busniess.service.IService.*(..))" />

        <aop:advisor advice-ref="txAdvice"

            pointcut-ref="serviceOperation" order="1" />

        <aop:aspect id="profilingAspect" ref="profiler">

            <!-- -->

            <aop:pointcut id="serviceMethodWithReturnValue"

                expression="execution(!void cn.xiangyunsoft.busniess.service..*Service.*(..))" />

            <!-- 通知类型为after-throwing 表示发生异常时通知,还有其他选择 -->

            <aop:after-throwing method="profile"

                pointcut-ref="serviceMethodWithReturnValue" />

        </aop:aspect>

    </aop:config>

 

</beans>

Service 层的bean 在另一个beans.xml文件配置

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <bean id="userService"

        class="cn.xiangyunsoft.busniess.service.UserServiceImpl">

        <property name="userDao" ref="userDao"></property>

    </bean>

    <bean id="userDao"

        class="cn.xiangyunsoft.busniess.dao.UserDao">

        <property name="sessionFactory" ref="sessionFactory"></property>

    </bean>

</beans>

还有一个执行通知的类

public class SimpleProfiler implements Ordered {

 

    private int order;

// allows us to control the ordering of advice

public int getOrder() {

return this.order;

}

public void setOrder(int order) {

this.order = order;

}

 

// this method is the around advice

public Object profile(ProceedingJoinPoint call) throws Throwable {

    System.out.println("事务执行完成");

Object returnValue;

StopWatch clock = new StopWatch(getClass().getName());

try {

clock.start(call.toShortString());

returnValue = call.proceed();

} finally {

clock.stop();

System.out.println(clock.prettyPrint());

}

return returnValue;

}

}

 

测试类:

public class BaseServiceTest extends AbstractTransactionalSpringContextTests {

    protected String[] getConfigLocations() {

        return new String[] { "classpath:/applicationContext_Test.xml",

                "beans.xml" };

    }

}

public class UserServiceTest extends BaseServiceTest {

 

    private UserService userService;

 

    public void setUserService(UserService userService) {

        this.userService = userService;

    }

 

    public UserService getUserService() {

        return userService;

    }

 

    @Test

    public void testLogin() {

        User user = new User("adm");

        user.setPassword("admin");

        userService.login(user);

    }

 

    @Test

    public void testSave() {

        User user = new User("122");

        user.setName("abc");

        userService.save(user);

    }

}

这两个测试方法一个成功,一个不成功就可以测试出通知发生在不同的时间了。

 

一点感想:

就是在读Spring手册时不够认真,这个事务配置了好几天,都是不成功,在网上也没有找到合适的解决方法,最后又仔细的读了一次手册,终于成功!教训~

posted on 2007-06-02 11:29 Libo 阅读(2085) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: