Spring编程<五>

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;
}

}
`
这样就能进行事务操作了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值