Spring编程<五>
Web中搭建Spring框架
必要的包:
架构类似于MVC:
配置Spring框架要用监听器实现:
在web.xml中配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:beans.xml,
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在配置文件中配置dao与service实现类:
<!--beans.xml -->
<bean id="studDao" class="cn.hncu.stud.dao.StudDaoJdbc">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="studDao2" class="cn.hncu.stud.dao.StudDaoJdbc2">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="service" class="cn.hncu.stud.service.StudServiceImpl">
<property name="dao1" ref="studDao"></property>
<property name="dao2" ref="studDao2"></property>
</bean>
applicationContext.xml是全局共享的容器,在这里写数据库连接:
<!-- 从配置文件中读取连数据库需要的数据,配置文件在/WEB-INF/conf-->
<context:property-placeholder location="WEB-INF/conf/jdbc.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="${diriver}">
</property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${pwd}"></property>
</bean>
因为service是由Tomcat生成,所有要在Servlet中覆盖初始化
@Override
public void init() throws ServletException {
//获取web项目中的spring容器
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
service = ctx.getBean("service", IStudService.class);
}
因为要进行事务,所有可以拦截service层,写切面:
在beans.xml中配置:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
<bean id="advisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="expression">
<value>execution( void cn.hncu.stud..StudServiceImpl.save(..) )</value>
</property>
<property name="advice">
<bean class="cn.hncu.stud.aop.AroundAdvice"></bean>
</property>
</bean>
<bean id="user" class="cn.hncu.stud.domain.User"></bean>
写一个自己的事务通知:
public class AroundAdvice implements MethodInterceptor,ApplicationContextAware{
ApplicationContext ctx = null;
//事务
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("事务开启");
DataSource dataSource=ctx.getBean("dataSource", DataSource.class);
Connection conn= dataSource.getConnection();
conn.setAutoCommit(false);
Object returnValue;
try {
returnValue = invocation.proceed();
conn.commit();
System.out.println("事务提交...");
return returnValue;
} catch (Exception e) {
System.out.println("事务回滚");
conn.rollback();
conn.close();
}
return null;
}
@Override
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
this.ctx=ctx;
}
但是由于这种情况大家都是从datasource中直接拿,所以可能拿的不是同一个Connection
在此,还需要拦截datasource中的getConnection方法():
在applicationContext.xml中配置新的切面:
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
<!-- 切面 -->
<bean id="advisor2"
class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="expression" value="execution(* *..*.getConnection())"></property>
<property name="advice" >
<bean class="cn.hncu.stud.aop.ConAdvice"></bean>
</property>
</bean>
用ConAdvice拦截getConnection();
“`
//使用代理工具时 cglib-nodep-2.1_3.jar
public class ConAdvice implements MethodInterceptor{
private ThreadLocal t = new ThreadLocal();
@Override
public Object invoke(MethodInvocation inv) throws Throwable {
Connection con = t.get();
if( con==null ){
final Connection con0=(Connection)inv.proceed();//放行 拦截的是getConnection()方法
//防止dao1关流conn,所有还要拦截close()方法
//要往本地线程池中放一个,被屏蔽掉close();的con
//对con0进行代理
Callback callback = new net.sf.cglib.proxy.MethodInterceptor(){
@Override
public Object intercept(Object proxeidObj, Method method,
Object[] args, MethodProxy proxy) throws Throwable {
if(method.getName().equals("close")){
//当拦截到close方法时,不进行操作
return null;
}
return method.invoke(con0, args);
}
};
//生成代理后的对象
con=(Connection) Enhancer.create(Connection.class, callback);
//把代理后的对象放回
t.set(con);
}
return con;
}
}
`
这样就能进行事务操作了。