Spring容器的动态代理proxy及面向切面aop实现业务层事务管理

  • 以前我们写的service,为图方便,就没有写IService接口,在使用时是自己new的,有两点需要指明:其一,如前面博文所说,最好写接口,并用反射的方式获取对象,这样换实现方式时,只用在配置文件中修改实现类名称,而无需改动源码;其二,之前我们并没有使用动态代理,所以要想引入事务,必须自己在业务层写commit,定义事务。
  • Spring容器为我们提供了很好的解决方案。Spring的IoC/DI使得容器不但给我们反射所需的实例,还可以在配置文件中给实例注入属性,而且还提供了事务管理。要想容器给我们管理事务,service实例就交由容器动态代理。
  • 面向切面,就是面向方法,在哪些方法里事务管理
    这里写图片描述
  • 如下的配置文件要谨记Beans3.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
">

<!-- 配数据源BasicDataSource 要两个jar包,dbcp,pool-->
<!--  commons-dbcp-1.4.jar-->
<!--  commons-pool-1.6.jar-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test"/>
    <property name="username" value="root"/>
    <property name="password" value="root1205"/>
    <property name="defaultAutoCommit" value="true"/>
</bean>


<!-- 注入jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!-- 这里面要配数据源 -->
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 将jdbcTemplate注入到PeopleService中 -->
<bean id="peopleService" class="com.service.PeopleService">
    <property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>


<!-- 配事务 需要spring里的aop,tx,[aspect]包还有另外的aopalliance.jar aspectjweaver.jar-->
<!-- 给数据源配事务管理,DataSourceTransactionManager-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 再使用tx标签,实现事务管理,这里tx标签不提示,要导入新的xsd -->
<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut expression="execution(* com.service.PeopleService.save(..))" id="txPointCut"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>

</beans>
  • PeopleService.java
package com.service;

import org.springframework.jdbc.core.JdbcTemplate;

import com.entity.People;

public class PeopleService implements IPeopleService {

    private JdbcTemplate jdbcTemplate;


    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }


    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }


    @Override
    public void save(People p) {
        //通过在save方法里打断点的方式可以看到通过spring容器实现的动态代理,使得业务层的数据库操作具有了事务功能
        //不用手动地每个方法里commit了
        jdbcTemplate.execute("insert into person(id,name)values(5,'张卫健')");
        jdbcTemplate.execute("insert into person(id,name)values(6,'张卫健2')");
    }

}
  • 测试类Demo2.java
package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

import com.service.IPeopleService;
import com.service.PeopleService;

public class Demo2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //使用jdbcTemplate操作数据库
        //Ctrl+Shift+T可以查找某个类是否存在,找不到就是少包
        //导入spring里的spring-jdbc-3.2.6.RELEASE.jar
//      ApplicationContext app = new ClassPathXmlApplicationContext("Beans3.xml");
//      JdbcTemplate jdbcTemplate = (JdbcTemplate) app.getBean("jdbcTemplate");
//      System.out.println(jdbcTemplate);
//      //要导入spring-tx-3.2.6.RELEASE.jar  mysql-connector-java-5.1.7-bin.jar
//      jdbcTemplate.execute("insert into person(id,name)values(5,'张卫健')");
//      jdbcTemplate.execute("insert into person(id,name)values(6,'张卫健2')");

        ApplicationContext app = new ClassPathXmlApplicationContext("Beans3.xml");
        //spring中有两种代理方式,默认优先jdk代理,再cglib代理
        //jdk代理必须使用接口,所以下面用的是接口,否则在代理时会报错
        //cglib代理使用的是子类,可以不用接口,spring内置了cglib,否则要另外导入cglib包
        //如下获得的peopleService是一个代理对象
        IPeopleService peopleService = (IPeopleService) app.getBean("peopleService");
        peopleService.save(null);
    }
}

jar包图
这里写图片描述

猜你喜欢

转载自blog.csdn.net/yicha_i/article/details/82735253
今日推荐