下面通过一个简单的实例来了解Spring的业务层即相关机制和配置
1、用户登录的UserService
package com.service;
import com.domain.User;
public interface UserService {
boolean hasMatchUser(String userName,String password);
User findUserByUserName(String userName);
void loginSuccess(User user);
}
2、Service实现
package com.service;
import com.dao.LoginLogDao;
import com.dao.UserDao;
import com.domain.LoginLog;
import com.domain.User;
public class UserServiceImpl implements UserService {
private UserDao userDao;
private LoginLogDao loginLogDao;
public boolean hasMatchUser(String userName, String password) {
int matchCount =userDao.getMatchCount(userName, password);
return matchCount > 0;
}
public User findUserByUserName(String userName) {
return userDao.findUserByUserName(userName);
}
public void loginSuccess(User user) {
user.setCredits( 5 + user.getCredits());
LoginLog loginLog = new LoginLog();
loginLog.setUserId(user.getUserId());
loginLog.setIp(user.getLastIp());
loginLog.setLoginDate(user.getLastVisit());
userDao.updateLoginInfo(user);
loginLogDao.insertLoginLog(loginLog);
}
public void setLoginLogDao(LoginLogDao loginLogDao) {
this.loginLogDao = loginLogDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
从上面的代码中我们可以看出:UserServiceImpl声明了userDao和loginLogDao两个属性,并提供了setXXX方法,这是为了通过Spring的配置文件完成DAO的注入。这里的两个属性和相应的setXXX方法都是Spring配置文件DAO注入值的接收器。此外,我们看不到任何的事物操作的代码,这是因为Spring让程序员从事务操作单调机械的代码中解脱出来,专注完成必不可少的工作。其他的由Spring容器来完成。通过Spring声明式事务配置即可以让业务类享受EJB声明式事务的优点。
接下来我们在Spring中为业务类UserService实现类实现事务管理能力和配置声明式事务。
3、Spring的事务管理和声明式事务配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans default-autowire="no"> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"> </property> </bean> <bean id="userServiceTarget" class="com.service.UserServiceImpl"> <property name="userDao" ref="userDao" /> <property name="loginLogDao" ref="loginLogDao"></property> </bean> <!-- 声明性事务 --> <bean id="userService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager" /> <property name="target" ref="userServiceTarget" /> <property name="transactionAttributes"> <props> <prop key="findUserByUserName"> PROPAGATION_REQUIRED,readOnly </prop> <prop key="hasMatchUser"> PROPAGATION_REQUIRED,readOnly </prop> <prop key="loginSuccess">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans>
在上面的配置文件中,作了以下几方面的配置:1是定义了一个基于数据源的DataSourceTransactionManager事务管理器,该事务管理器负责声明式事务管理,该管理器需要设置dataSource属性。在这个配置文件中没有定义,但已经在上一个博客(Spring的DAO装载)的配置中定义,在后面将讲述怎样将两个或多个配置文件在运行期整合在一起。所以这里就不进行配置,而是直接使用已经配置好的相应的BEAN ID。2是定义了业务类具体实现Bean。该类中有两个DAO属性,在这里进行属性的值的注入。3配置声明式事务。声明式事务可以配置3个属性:transactionManager(对目标类的方法进行事务管理)、target(需要代理的目标业务类)和transactionAttributes(定义目标业务类中的那些方法需要事务的支持)。在transactionAttributes中定义方法的事务控制属性。这里介绍几个常用的事务控制属性(事务传播类型):PROPAGATION_REQUIRED--较常用,表示业务方法在当前线程中查看是否有事务支持,有就利用这个事务,否则创建一个新的事务。readOnly——表示事务是只读事务,可以提高运行效率。
此外,在配置transactionAttributes中的方法名时,可以使用"*"通配符。
4、Spring配置文件的整合
我么可以在web.xml中进行配置来再Web容器启动时自动启动Spring容器。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dao.xml,classpath:service.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- 使用自动启动的Servlet进行初始化 --> <!-- servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet--> <servlet> <servlet-name>myweb</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>myweb</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app>
从上面的配置中我们可以看出:1是spring配置文件的整合是在<context-param> <param-value>classpath:dao.xml,classpath:service.xml</param-value>
</context-param>中用classpath:配置文件名表示一个配置文件,并用逗号分隔多个配置文件的方式来进行多个配置文件的整合,然后用一个Listener来监听这些配置。2是同Struts一样,加载一个Servlet来引入Spring。