Spring中服配Service和Spring配置文件的整合

Spring中装配Service和Spring配置文件的整合

下面通过一个简单的实例来了解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。