zoukankan      html  css  js  c++  java
  • Spring---AOP注解开发&jdbc模板&Spring事务管理

    一、AOP注解开发

      此处需要回忆一遍AOP的概念。简单的来说,AOP就是利用动态代理技术,做到不触动源代码但却扩展了功能。那么就需要一个被扩展的对象和一个“新的功能”,例如说给某类的saveUser方法增加输出日志需求,此时输出日志该事件就是一个“新的功能”。举这个例子的重点只是为了突出,AOP技术需要关注两个方面,一个是接受者,而另一个是输出点。要利用AOP,必然需要将这两个对象做出关联。而所谓AOP注解开发,就是如何将这两个对象建立关系。

      当然,以上理解仅仅为个人的话语解读,不具有严谨的用词,有任何理解错误,望不吝赐教。

      在AOP的xml开发中,xml核心配置如下

    <aop:config>
        <--切入点(接受对象)-->
        <aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))" id="aa"/>
        <--切面(新功能)-->
        <aop:aspect ref="logger"> 
        <aop:before method="log" pointcut-ref="aa"/>
        </aop:aspect>
    </aop:config>

      因此,注解只需要做到清楚表达以上两点内容,再配套一些基本的要求,例如托管类。此外,为了让程序的复用性更强,我们只需要对“新功能”对象做处理,告诉它要为谁增强方法即可做到关联,以下为实例:

    • 导入jar包 aop联盟包、 aspectJ实现包 、 spring-aop-xxx.jar 、 spring-aspect-xxx.jar
    • 导aop约束 ,打开扫描约束开关<aop:aspectj-autoproxy/>
    • 托管两个类,在类上加注解@Compone
    •  然后再“新的功能”类上配置注解
    @Aspect //这个注解,是和aop有关,用于表示该类是一个功能扩展类,专门用来做增强的。
    public class Logger {
        @Before("execution(* com.gaga.service.impl.*.*(..))")
        public void log(){
            System.out.println("输出日志了~~~!");
        }

    二、jdbc模板

      所谓jdbc模板,就是Spring对于dao层的技术支持。和DBUtils的功能的目的是一样的,就是为了操作数据库。回想以下,如果什么框架都没有,只有java原生代码提供给我们的prepareStatement、createStatement、遍历resultSet那一套东西。那我们的操作便会过于臃肿。

      虽然操作数据库有更专业的框架,例如HibernateMybatis等等。但作为一个负责Service层的框架,自然会有向两边扩展的思想,因此便有了该部分模板。

      spring其实对dao层的大部分技术有提供模板支持

    1. 例子:
    public void testDemo(){
            
            //数据源,连数据库。 连什么类型的数据, 哪个库, 账号 & 密码
            DriverManagerDataSource dataSource  =new DriverManagerDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql:///stus");
            dataSource.setUsername("root");
            dataSource.setPassword("root");
            
            //1. 创建jdbc模板
            JdbcTemplate jdbcTemplate = new JdbcTemplate();
            jdbcTemplate.setDataSource(dataSource);
                    
            String sql = "insert into t_user values(null , ? , ? )";
            
            //2. 执行添加操作,其实它的用法和以前的queryrunner一样。
            jdbcTemplate.update(sql , "66666","zhangsan");
        }

      2.配置C3P0连接池(注入写法)

      为了方便修改数据库连接信息,通常在src下使用properties文件来记录他们。主要是方便修改

    •   导入Jar包  c3p0-0.9.5.2.jar   mchange-commons-java-0.2.12.jar
    •   配置xml
      •  在src下新建一个properties文件,内容如下 名:jdbc.properties
    driverClass=com.mysql.jdbc.Driver
    jdbcUrl=jdbc:mysql:///user
    user=root
    password=root
      •  在xml里面导入jdbc.properties ,并且在dataSource里面引用
        <bean id="us" class="com.gaga.service.impl.UserServiceImpl">
                <property name="userDao" ref="userDao"></property>
        </bean>
        
        <bean id="userDao" class="com.gaga.dao.impl.UserDaoImpl">
                <property name="jdbcTemplate" ref="jdbcTemplate"></property>
        </bean>
        
        
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                <property name="dataSource" ref="dataSource"></property>
        </bean>
         
         <context:property-placeholder location="classpath:jdbc.properties"/>
                    <!-- 使用c3p0连接池 -->
                  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                      <property name="driverClass" value="${driverClass}"></property>
                      <property name="jdbcUrl" value="${jdbcUrl}"></property>
                      <property name="user" value="${user}"></property>
                      <property name="password" value="${password}"></property>
                  </bean>

      以上配置将servicedaojdbcTemplate连接池都用IOC做了托管,并且用了DI注入,也就是说1.例子中的一堆堆代码可以简化为如下。只需要声明模板,然后直接可以使用,创建对象什么的都交给Spring。核心便是这个

    @Repository("ud")
    public class UserDaoImp implements UserDao {
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            System.out.println("userDao的set方法---");
            this.jdbcTemplate = jdbcTemplate;
        }
        @Override
        public void save() {
            String sql = "insert into bbb values(null,?)";
            jdbcTemplate.update(sql, "66666666");
        }
    }

    三、Spring事务管理

      正如标题所述,Spring会对事务做管理。但需要注意只是做管理,实际操作还是依据不同的框架的做法(不同的实现)。

      这里不得不提,Spring其中的伟大之一在于AOP。那么我们就可以利用它来对某部分功能加入事务的功能。而,当我们要利用Spring来进行事务管理的时候,正所谓人在屋檐下,不得不低头。你用人家的,那也得遵守别人定下的规矩。

      Spring统一规定,要操作事务,必须使用管理员!

    管理事务的规范是 : PlatformTransactionManager
        jdbc | mybatis : DataSourceTransactionManager
        hibernate : HibernateTransactionManager

      Spring对事务的支持,有三种写法:编程式事务、xml声明式事务、注解声明式事务。

      这三种写法中,最简介的为注解式事务。以下列出三种写法的实例,推荐后者。

    • 编程式事务
       1   @Test
       2       public void test(){
       3 
       4 
       5           //事务的管理员是用来管理事务的,包含了打开事务、 提交事务、 回滚事务
       6           final DriverManagerDataSource dataSource = new DriverManagerDataSource();
       7           dataSource.setDriverClassName("com.mysql.jdbc.Driver");
       8           dataSource.setUrl("jdbc:mysql:///stus");
       9           dataSource.setUsername("root");
      10           dataSource.setPassword("root");
      11 
      12 
      13           DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
      14           transactionManager.setDataSource(dataSource);
      15 
      16           //1. 创建事务的模板对象。
      17           TransactionTemplate transactionTemplate = new TransactionTemplate();
      18           transactionTemplate.setTransactionManager(transactionManager);
      19 
      20           //事务事务的模板对象
      21           transactionTemplate.execute( new TransactionCallback<Object>() {
      22 
      23               //在事务里面执行这个方法。
      24               @Override
      25               public Object doInTransaction(TransactionStatus arg0) {
      26 
      27                   //添加操作
      28                   JdbcTemplate jdbcTemplate = new JdbcTemplate();
      29                   jdbcTemplate.setDataSource(dataSource);
      30 
      31                   String sql = "insert into  t_user values ( null , ? , ?)";
      32                   jdbcTemplate.update(sql, "123","王五");
      33 
      34                   int a = 1 / 0 ;
      35 
      36                   jdbcTemplate.update(sql, "6666","赵六");
      37 
      38                   return null;
      39               }
      40           });
      41 
      42       }
      编程式事务
    • xml声明式事务
     1    <!-- 以下属于事务的配置 如果要用事务了,那么事务的管理员是谁啊。 -->
     2        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     3            <property name="dataSource" ref="dataSource"></property>
     4        </bean>
     5      
     6        <!-- 
     7            以上配置,到目前为止,只是说明了,如果要开启事务,管理员是谁。 但是缺少了一个东西。
     8            就是哪一个方法到底要用事务呀? --> 
     9        <aop:config>
    10            <aop:pointcut expression="execution(* com.gaga.service.impl.*.*(..))" id="aa"/>     
    11            <aop:advisor advice-ref="advice01" pointcut-ref="aa"/>
    12        </aop:config>
    13 
    14        <tx:advice id="advice01" transaction-manager="transactionManager">
    15            <tx:attributes>  <!-- 对 id="aa"表达式找到的那一堆方法,进行过滤配置,表示谁才能用事务管理, 如果是* ,表示前面找到的那一堆都用事务管理 -->
    16                <tx:method name="save*"/>
    17                <tx:method name="update*"/>
    18                <tx:method name="delete*"/>
    19            </tx:attributes>
    20        </tx:advice>
    xml声明式事务
    • 注解声明式事务

        a)xml中的配置

    <context:component-scan base-package="gaga"/>
        <aop:aspectj-autoproxy/>
    1. 在xml中 声明注解事务的管理员
    
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${driverClass}"/>
            <property name="jdbcUrl" value="${jdbcUrl}"/>
            <property name="user" value="${user}"/>
            <property name="password" value="${password}"/>
        </bean>
       <!-- 以下属于事务的配置 如果要用事务了,那么事务的管理员是谁啊。 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
               <property name="dataSource" ref="dataSource"></property>
           </bean>
           
           <!-- 指定注解事务使用的管理员是谁 -->
           <tx:annotation-driven transaction-manager="transactionManager"/>

        b) 代码配置

    2. 在业务逻辑类上或者方法上打注解
    
            类上的注解,表示类中的所有方法都用事务, 如果在方法上打注解,表示只有这个方法才会用事务
                @Transactional
                public class UserServiceImpl implements UserService {
    
                }
                public class UserServiceImpl implements UserService {
                   // @Transactional
                    @Override
                    public void save() {
                }
  • 相关阅读:
    互斥锁Mutex与信号量Semaphore的区别
    c/c++强制类型转换
    c++中的隐藏、重载、覆盖(重写)
    运算符重载详解
    类的大小
    C++ static、const和static const 以及它们的初始化
    一种隐蔽性较高的Java ConcurrentModificationException异常场景
    Java编码常见的Log日志打印问题
    Java编程常见缺陷汇总(一)
    Java字符串连接的多种实现方法及效率对比
  • 原文地址:https://www.cnblogs.com/sanmaotage/p/8412794.html
Copyright © 2011-2022 走看看