Spring编程<五>

来源:互联网 发布:淘宝借贷利息 编辑:程序博客网 时间:2024/05/22 14:23

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();

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

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

原创粉丝点击