美文网首页
Spring小结

Spring小结

作者: 唯黑 | 来源:发表于2018-02-01 14:43 被阅读0次

1、IOC 容器

1、概念

  • IOC为Inversion of control,控制反转,意思是现在需要对象,自己不创建,交给外部的容器创建
  • IOC容器= bean.xml配置 + ApplicationContext容器类

2、简单使用

  • 引入jar

    commons-logging-1.1.3.jar       【单独下载】
    spring-beans-3.2.5.RELEASE.jar        【spring源码, bean节点管理】
    spring-context-3.2.5.RELEASE.jar      【spring上下文类】
    spring-core-3.2.5.RELEASE.jar         【IOC容器】
    spring-expression-3.2.5.RELEASE.jar    【spring表达式】
    
  • 新建applicationContext.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:p="http://www.springframework.org/schema/p"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd">
    
    </beans> 
    
  • 配置

    <bean id="userAction " class="xxxx.UserAction ">
    </bean>
    
  • 获取

    // 容器对象(加载applicationContext.xml配置文件)
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 获取对象
    UserAction userAction = (UserAction) ac.getBean("userAction");
    userAction.execute();
    

3、配置细节

  • 细节1

    id 不能以数字开头,不能含有特殊符号, 不能有空格、逗号等, id 不能重复
    name 可以以数字开头,可以有特殊符合,如果name值重复,编译没有问题但运行报错
    <bean id="user" name="user2,user3 user4" class="xxxx.User"></bean>
    <bean name="user5" class="xxxx.User"></bean>
    <bean id="user6" class="xxxx.User"></bean>
    <bean id="user6" class="xxxx.User"></bean>
    
  • 细节2

     <!-- 
          scope="singleton"   默认表示单例!
                 prototype    多例
          init-method=""      在创建完对象之后执行初始化方法
          destroy-method=""   在调用容器类的destroy()方法时候,对单例的对象有效!
          lazy-init="true"    延迟初始化 / 这个属性的设置只对单例有影响,对多例没有任何影响!
                              单例的对象默认是在创建容器的时候就创建所有单例的对象,如果希望在第一次访问的时候创建单例的对象,就设置延迟初始化
          Bean生命周期:
             bean在xml中配置,
                singleton  单例
                  1) 创建对象
                       如果有配置延迟初始化,
                          lazy-init=true  如果单例的对象有配置延迟初始化, 在创建容器之后,在第一次从容器获取对象的时候
                                       创建单例的对象!
                      如果没有配置或延迟初始化为默认值, 单例的对象会在创建容器的时候创建对象
                  2) 执行初始化方法 , init-method配置的方法会执行
                  3) 调用容器destroy() 方法时候,容器在销毁单例对象的实例的时候,会调用destroy-method对应的方法
                     此时bean对象会被销毁!
                
                prototype  多例
                   1) 每次在从容器获取对象的时候,都会创建新的对象
                   2) 每次创建完对象后,就执行初始化方法
                   3) java回回收不用资源(jvm gc)     
       -->
      <bean id="user" 
          class="xxxx.User" 
          init-method="init" 
          destroy-method="destroy_" 
          lazy-init="false" 
          scope="prototype"></bean>
    

4、创建对象的几种方式

  • 构造赋值

    <!-- 创建user对象,且赋值 -->
    <!-- 
      value 当直接给属性值的时候使用value赋值
      ref   当引用的是IOC容器中的对象的时候,使用ref    
     -->
    <bean id="user" class="xxxx.User">
      <constructor-arg index="0" type="int" value="10000"></constructor-arg>
      <constructor-arg index="1" type="String" ref="str"></constructor-arg>
    </bean>
    
  • set赋值

    <!--IOC容器, 给对象属性赋值 -->
    <bean id="user" class="xxxx.User">
      <property name="id" value="1000"></property>
      <property name="name" value="Jacky"></property>
      <!-- list集合赋值 -->
      <property name="list">
          <list>
              <value>cn</value>
              <value>usa</value>
          </list>
      </property>
      <!-- map 集合赋值 -->
      <property name="map">
          <map>
              <entry key="cn" value="China"></entry>
              <entry key="usa" value="1234"></entry>
          </map>
      </property>
      <!-- Properties对象赋值 -->
      <property name="prop">
          <props>
              <prop key="cn">China</prop>
              <prop key="usa">America</prop>
          </props>
      </property>
    </bean>
    
  • 工厂创建对象

     <!-- 
        class 指定工厂的类型;  
        factory-method: 工厂类的静态方法
    -->
     <bean id="user1" class="xxxx.UserFactory" factory-method="getStaticInstance"></bean>
    
       <!-- * 非静态方法创建对象 -->
      <!-- 先创建工厂实例 -->
     <bean id="factory" class="xxxx.UserFactory"></bean>
     <bean id="user" factory-bean="factory" factory-method="getInstance"></bean>
    
  • p名称空间

    <bean id="str" class="java.lang.String">
     <constructor-arg value="Jacky"></constructor-arg>
    </bean>
    <bean id="user" class="xxxx.User" p:id="1000" p:name-ref="str"></bean>
    
  • 自动装配

    <?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:p="http://www.springframework.org/schema/p"
          xmlns:context="http://www.springframework.org/schema/context"
          xsi:schemaLocation="
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd" 
              default-autowire="byType">
          
          <!-- 配置: 需要创建的对象、对象依赖关系处理 -->
          
          <!-- 方式4:自动装配 (了解) -->
          <!-- 
              a. default-autowire="byType"  配置到全局
                  当前所有的bean都采用”根据类型自动装配“
              b. 配置到bean节点
                  autowire="byName"  根据名称自动装配, 会去容器找指定名称的对象,注入到set方法的参数中!
                  autowire="byType"  根据类型自动装配, 要确保改类型对应的对象在IOC容器中唯一,否则报错!
                  
              总结:
                  简化配置,但是维护麻烦!
           -->
          <bean id="userDao" class="xxx.UserDao"></bean>
          <bean id="userService" class="xxx.UserService"></bean>
          <bean id="userAction" class="xxx.UserAction"></bean>
    
      </beans>      
    
  • 注解

    <!-- 1. 开启注解扫描 -->
    <context:component-scan base-package="xxxx"></context:component-scan>
    
      // 把userDao对象加入IOC容器
      //@Component("userdao")  // <bean id=userDao class="...">
      //@Repository("userdao")  // <bean id=userDao class="...">
    
      @Repository   // 默认名称是类名,且第一个字母小写
      public class UserDao implements IUserDao {
          // 模拟:保存对象
          public void save() {
              System.out.println("UserDao.save()");
          }
      }
    //@Component("userService")  // 把当前类加入IOC容器
      //@Service("userService")  // 把当前类加入IOC容器
      @Service
      public class UserService implements IUserService {
          
          //@Resource(name = "userDao")   // 根据”userDao“去ioc容器找对象,找到后注入到当前方法参数
          
          @Resource       // 默认会根据private IUserDao userDao 这里的名称去容器找; 如果没有找到,再根据类型找,再没有找到就报错!
          private IUserDao userDao;
    
          public void save() {
              userDao.save();
          }
      }
    
    
      //@Component("userAction")  // 加入IOC容器
      //@Controller("userAction")  // 加入IOC容器
      @Scope("prototype")       // 指定加入ioc容器的对象为多例
    
      @Controller
      public class UserAction {
          
      //  @Resource(name = "userService")  // ioc容器找名称是userService的对象并注入
          
          @Resource
          private IUserService userService;
          
          public String execute(){
              userService.save();
              return "success";
          }
      }
    

2、Spring与Struts2整合

1、关键

  • 把action的创建,交给spring的ioc容器

2、引入jar

  • struts2-spring-plugin-2.3.4.1.jar 【struts源码】
  • spring-web-3.2.5.RELEASE.jar 【spring源码】

3、配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- struts2配置 -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Spring配置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/bean*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

3、Aop编程

1、概念

  • Aop编程:关注点代码与业务代码分离(jdk/cglib代理)
  • 关注点:重复执行的代码, 也叫关注点代码
  • 切面:关注点代码形成的类,就叫做切面

2、步骤

  • 引入jar

    aopalliance.jar               【spring-framework-2.5.6\lib\aopalliance】
    aspectjrt.jar                【spring-framework-2.5.6\lib\aspectj】
    aspectjweaver.jar             【spring-framework-2.5.6\lib\aspectj】
    spring-aop-3.2.5.RELEASE.jar     【Spring3.2源码】
    
  • 引入aop名称空间和开启aop注解

    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop.xsd">
    
      <!-- 开启注解扫描 -->
      <context:component-scan base-package="xxxx"></context:component-scan>
      <!-- 开启aop注解 -->
      <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
  • 使用Aop相关注解

      // 重复代码
      @Component("aop")
      @Aspect      // 指定一个类为切面类
      public class TransactionAop {
          
          // 定义一个切入点表达式变量  (后面使用这个切入点表达式的时候,直接引用方法名即可)
          @Pointcut("execution(* xxxx.UserDao.*(..))")
          public void pointcut_(){
          }
    
          //【前置通知】
          // 在执行业务方法,之前执行
          @Before("pointcut_()")
          public void beginTransaction() {
              System.out.println("[前置通知]  开启事务..");
          }
          
          //【后置通知】
          // 在执行业务方法,之后执行
          @After("pointcut_()")
          public void commit() {
              System.out.println("[后置通知] 提交事务..");
          }
          
          // 【返回后通知】   在执行目标方法结束后执行, 出现异常不会执行
          @AfterReturning("pointcut_()")
          public void afterReturing(){
              System.out.println("[返回后通知]");
          }
          
          // 【异常通知】   在执行目标方法的时候出现异常执行
          @AfterThrowing("pointcut_()")
          public void afterThrowing(){
              System.out.println("[异常通知]");
          }
          
          // 【环绕通知】 会环绕目标方法执行
          @Around("pointcut_()")
          public void arroud(ProceedingJoinPoint pjp) throws Throwable{
              System.out.println("[环绕前:]");
              pjp.proceed();                 // 执行目标方法
              System.out.println("[环绕后:]");
          }
    
      }
    
  • 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:context="http://www.springframework.org/schema/context"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xsi:schemaLocation="
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop.xsd">
          
          <!-- dao实例加入容器 -->
          <bean id="userDao" class="xxxxx.UserDao"></bean>
          
          <!-- 实例化切面类 -->
          <bean id="aop" class="xxxx.TransactionAop"></bean>
          
          <!-- Aop相关配置 -->
          <aop:config>
              <!-- 切入点表达式定义 -->
              <aop:pointcut expression="execution(* xxxx.UserDao.*(..))" id="pt"/>
              
              <!-- 切面配置 -->
              <aop:aspect ref="aop">
              
                  <!-- 【环绕通知】 -->
                  <aop:around method="arroud" pointcut-ref="pt"/>
              
                  <!-- 【前置通知】 在目标方法之前执行 -->
                  <aop:before method="beginTransaction" pointcut-ref="pt" />
                  
                  <!-- 【后置通知】 -->
                  <aop:after method="commit" pointcut-ref="pt"/>
                  
                  <!-- 【返回后通知】 -->
                  <aop:after-returning method="afterReturing" pointcut-ref="pt"/>
                  
                  <!-- 异常通知 -->
                  <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
                  
                  
              </aop:aspect>
          </aop:config>
          
      </beans>
    

3、切入点表达式语法详解

  • 切入点表达式:拦截指定的类,生成代理对象

  • 表达式

     execution(
      modifiers-pattern?                  拦截的方法的访问修饰符
      ret-type-pattern                   方法返回类型,必须指定
      declaring-type-pattern?             拦截的方法所在的类
      name-pattern(param-pattern)       拦截的方法(以及方法的参数列表)
      throws-pattern?)                  方法声明的异常
    
      <!-- 切入点表达式定义 -->
      
      <!-- 1. 拦截指定的方法(通用)  -->
      <!--<aop:pointcut expression="execution(* xxxx.UserDao.save(..))" id="pt"/>-->
      
      <!-- 2. 拦截指定的类下所有的方法 -->
      <!--<aop:pointcut expression="execution(* xxxx.UserDao.*(..))" id="pt"/>-->
      
      <!-- 3. 拦截指定包下所有的类的所有方法 -->
      <!--<aop:pointcut expression="execution(* xxxx.*.*(..))" id="pt"/>-->
      
      <!-- 3. 拦截指定包,以及其子包下所有类的所有方法 -->
      <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
      
      <!-- 5. 拦截所有的public方法 -->
      <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
      
      <!-- 6. 拦截所有的包含save方法 -->
      <!--<aop:pointcut expression="execution(* *save*(..))" id="pt"/>-->
      
      <!-- 7. 拦截UserDao.save()方法与OrderDao.save() -->
      <!--<aop:pointcut expression="execution(* cn..UserDao.save(..)) || execution(* cn..OrderDao.save(..))" id="pt"/>-->
      <!--<aop:pointcut expression="execution(* cn..UserDao.save(..)) or execution(* cn..OrderDao.save(..))" id="pt"/>-->
      
      <!-- 8. 不拦截UserDao.save()方法 -->
      <!--<aop:pointcut expression="!execution(* cn..UserDao.save(..))" id="pt"/>-->
      <!--<aop:pointcut expression=" not execution(* cn..UserDao.save(..))" id="pt"/>-->
      
      <!-- 9. 拦截UserDao.save()同时拦截OrderDao.save() -->
      <!-- 注意: 这种很少用,一般都是或者的关系即: || 、 or  -->
      <!--<aop:pointcut expression="execution(* cn..UserDao.save(..)) and execution(* cn..OrderDao.save(..))" id="pt"/>-->
      <aop:pointcut expression="execution(* cn..UserDao.save(..)) &amp;&amp; execution(* cn..OrderDao.save(..))" id="pt"/>
    

4、Spring对jdbc模块的支持

1、配置

  • db.properties

    driverClass=com.mysql.jdbc.Driver
    jdbcUrl=jdbc:mysql:///hib_demo
    user=root
    password=root
    initialPoolSize=3
    maxPoolSize=6
    acquireIncrement=2
    
  • applicationContext

    <?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:context="http://www.springframework.org/schema/context"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xsi:schemaLocation="
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop.xsd">
          
          <!-- 加载Proerties配置文件 -->
          <context:property-placeholder location="classpath:xxxx/db.properties"/>
          
          <!-- 1.  实例化连接池  -->
          <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>
              <property name="initialPoolSize" value="${initialPoolSize}"></property>
              <property name="maxPoolSize" value="${maxPoolSize}"></property>
              <property name="acquireIncrement" value="${acquireIncrement}"></property>
          </bean>
          
          <!--  2. 创建JdbcTemplate对象 -->
          <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
              <property name="dataSource" ref="dataSource"></property>
          </bean>
          
          <!-- 实例化dao -->
          <bean id="deptDao" class="xxxx.DeptDao">
              <property name="jdbcTemplate" ref="jdbcTemplate"></property>
          </bean>
          
      </beans> 
    
  • JdbcTemplate Api

    public class DeptDao implements IDeptDao {
          
          // 接收容器注入的JdbcTemplate对象
          private JdbcTemplate jdbcTemplate;
          public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
              this.jdbcTemplate = jdbcTemplate;
          }
          
    
          // 1. 原始jdbc代码
          public void save(Dept dept) {
              jdbcTemplate.update("insert into t_dept(deptName) values(?)", dept.getName());
          }
    
    
          @Override
          public void delete(Serializable id) {
              jdbcTemplate.update("delete from t_dept where id=?", id);
          }
          
          @Override
          public void update(Dept dept) {
              jdbcTemplate.update("update t_dept set deptName=? where id=?", dept.getName(),dept.getId());
          }
    
    
          @Override
          public Dept findById(Serializable id) {
              // queryForList 把每一行都封装为map对象,再添加到list中
      //      List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from t_dept");
              
              // 传入类型参数,表示查询的列的类型;  这里只能查询一列
      //      List<String> list = jdbcTemplate.queryForList("select deptName from t_dept", String.class);
    
               List<Dept> list = jdbcTemplate.query("select * from t_dept where id=?",  new MyRowMapper(), id);
              
              return (list!=null&&list.size()>0)?list.get(0):null;
          }
    
    
          @Override
          public List<Dept> getAll() {
              List<Dept> list = jdbcTemplate.query("select * from t_dept", new MyRowMapper());
              return list;
          }
          
          
          
          // 封装Springjdbc查询的结果集
          class MyRowMapper implements RowMapper<Dept>{
              
              // 如何解析一行
              @Override
              public Dept mapRow(ResultSet rs, int rowNum) throws SQLException {
                  Dept dept = new Dept();
                  dept.setId(rs.getInt("id"));
                  dept.setName(rs.getString("deptName"));
                  return dept;
              }
              
          }
          
      }     
    

5、Spring声明式事务管理

1、Jdbc(DataSourceTransactionManager)

  • 引入jar
    Spring 核心
    Spring Aop 切面编程
    Spring-jdbc / Spring-tx / 驱动包、连接池

  • 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:p="http://www.springframework.org/schema/p"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:aop="http://www.springframework.org/schema/aop" 
          xmlns:tx="http://www.springframework.org/schema/tx"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop.xsd
               http://www.springframework.org/schema/tx
               http://www.springframework.org/schema/tx/spring-tx.xsd">
    
          <!-- 1. 数据源配置 -->
          <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
              <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
              <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property>
              <property name="user" value="root"></property>
              <property name="password" value="root"></property>
              <property name="initialPoolSize" value="3"></property>
              <property name="maxPoolSize" value="6"></property>
          </bean>
    
          <!-- 2. JdbcTemplate配置 ,  注入数据源-->
          <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
              <property name="dataSource" ref="dataSource"></property>
          </bean>
    
          <!-- 3. dao实例,注入jdbcTemplate -->
          <bean id="deptDao" class="xxxx.DeptDao">
              <property name="jdbcTemplate" ref="jdbcTemplate"></property>
          </bean>
          
          <!-- 4. Service实例,注入dao实例 -->
          <bean id="deptService" class="xxxx.DeptService">
              <property name="deptDao" ref="deptDao"></property>
          </bean>
    
          <!-- 5. Spring声明式事务管理配置 -->
          
          <!-- 5.1 配置事务管理器类 -->
          <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource"></property>
          </bean>
          
          <!-- 5.2 事务通知配置, 拦截到指定的方法后如何管理事务 -->
          <!-- find*  find开头的方法,是只读的事务 -->
          <!--   *    上面所有的方法都不满足时候,采用的事务控制规则 -->
          <tx:advice id="txAdvice" transaction-manager="txManager">
              <tx:attributes>
                  <tx:method name="find*" read-only="true"/>
                  <tx:method name="get*" read-only="true"/>
                  <tx:method name="*" read-only="false"/>
              </tx:attributes>
          </tx:advice>
          
          <!-- 5.3 事务Aop配置 = 切入点表达式  + 应用上面的事务通知 -->
          <aop:config>
              <aop:pointcut expression="execution(* cn..*Service.*(..))" id="pt"/>
              <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
          </aop:config>
    
      </beans>     
    
  • 注解方式

      <?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:p="http://www.springframework.org/schema/p"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:aop="http://www.springframework.org/schema/aop" 
          xmlns:tx="http://www.springframework.org/schema/tx"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop.xsd
               http://www.springframework.org/schema/tx
               http://www.springframework.org/schema/tx/spring-tx.xsd">
    
          <!-- 1. 数据源配置 -->
          <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
              <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
              <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property>
              <property name="user" value="root"></property>
              <property name="password" value="root"></property>
              <property name="initialPoolSize" value="3"></property>
              <property name="maxPoolSize" value="6"></property>
          </bean>
    
          <!-- 2. JdbcTemplate配置 ,  注入数据源-->
          <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
              <property name="dataSource" ref="dataSource"></property>
          </bean>
          
          <!-- 事务管理器类 -->
          <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <property name="dataSource" ref="dataSource"></property>
          </bean>
          
          <!-- 开启注解扫描 -->
          <context:component-scan base-package="xxxx"></context:component-scan>
          <!-- spring声明式事务管理,注解开启 -->
          <tx:annotation-driven transaction-manager="txManager"/>
    
          
    
      </beans>     
    
    
    @Repository    // 当期类加入ioc容器
    public class DeptDao implements IDeptDao {
    
      // 注入JdbcTemplate对象
      @Resource
      private JdbcTemplate jdbcTemplate;
    
      public void save() {
          jdbcTemplate.update("insert into t_dept(deptName)values('test..')");
      }
    }
    
    @Service
    public class LogService {
    
        @Resource
        private JdbcTemplate jdbcTemplate;
    
        // 事务控制
            //@Transactional,写到方法上, 表示当前方法应用事务控制
                              写到类上,  表示当前类的所有方法都会应用事务
                              写到父类上, 当执行父类的这个方法时候才应用事务
        @Transactional(propagation=Propagation.REQUIRES_NEW)
        public void insertLog() {
            jdbcTemplate.update("insert into t_log values('在插入部门....')");
        }
    
    }
    
    @Service
    public class DeptService implements IDeptService {
    
      @Resource
      private IDeptDao deptDao;
      
      @Resource
      private LogService logService;
      
      // 当前方法应用事务
      @Transactional(
              readOnly=false,      // 读写的事务,当修改数据时候用;如果查询就设置为true
              isolation=Isolation.DEFAULT,  // 事务隔离级别
              timeout=-1,         // 事务执行的超时时间, -1 表示不超时
              //noRollbackFor=ArithmeticException.class,   // 遇到指定的异常不回滚
              propagation=Propagation.REQUIRED      // 事务传播行为
             //REQUIRES_NEW  当前执行方法必须在事务环境下运行,且当前执行方法始终开启一个新的事务
             //REQUIRED   当前执行方法必须在事务环境下运行,
                          如果调用当前方式时候已经有一个事务环境,当前执行方法会加入当前事务环境,就不开启新的事务,
                          如果调用当前方法时候没有事务环境,就开启一个新的事务!
             //SUPPORTS       支持事务环境! 如果当前方法没有事务,也可以运行!
            //Never           当前方法不能再事务环境下运行!
      )
      public void save() {
          // 插入日志
          logService.insertLog();
          
          int i = 1/0;
          
          // 插入部门
          deptDao.save();
      }
    }
    

2、 Hibernate(HibenateTransactionManager)

  • 引入jar
    hibernate jar
    spring – core
    spring – aop
    spring – orm 对orm支持
    spring-jdbc-3.2.5.RELEASE.jar
    spring-orm-3.2.5.RELEASE.jar
    spring-tx-3.2.5.RELEASE.jar

  • Spring创建SessionFactory几种方式

     <?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:p="http://www.springframework.org/schema/p"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context.xsd
          http://www.springframework.org/schema/aop
          http://www.springframework.org/schema/aop/spring-aop.xsd
          http://www.springframework.org/schema/tx
          http://www.springframework.org/schema/tx/spring-tx.xsd">
          
     <!-- 连接池, 通过spring管理 -->
     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
         <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property>
         <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
         <property name="user" value="root"></property>
         <property name="password" value="root"></property>
         <property name="initialPoolSize" value="3"></property>
         <property name="maxPoolSize" value="6"></property>
     </bean>
          
     <!-- Spring 与   Hibenate整合  (Spring创建SessionFactory) -->     
    
     <!-- 方式1: 直接加载hibernate.cfg.xml的方式,创建sessionFactory对象
     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
         <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
     </bean>
      -->
      
      <!-- 方式2: 连接池交给spring管理,其他配置还是写到hibernate.cfg.xml中 
      <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
         <property name="dataSource" ref="dataSource"></property>
         <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
      </bean>
      -->
      
      <!-- 方式3:(推荐) 所有的配置都在spring中完成-->
      <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
         <!-- a. 注入连接池 -->
         <property name="dataSource" ref="dataSource"></property>
         
         <!-- b. hibernate常用配置: 方言、自动建表、显示sql -->
         <property name="hibernateProperties">
             <props>
                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                 <prop key="hibernate.show_sql">true</prop>
                 <prop key="hibernate.hbm2ddl.auto">update</prop>
             </props>
         </property>
         
         <!-- c. 加载所有的映射(根据路径加载) 
         <property name="mappingLocations">
             <list>
                 <value>classpath:xxx/entity/*.hbm.xml</value>
             </list>
         </property>
         -->
         <!-- c. 根据目录加载所有的映射 -->
         <property name="mappingDirectoryLocations">
             <list>
                 <value>classpath:xxx/entity</value>
             </list>
         </property>
      </bean>
    
    
     <!-- 创建dao实例 -->
     <bean id="deptDao" class="xxx.DeptDao">
         <property name="sessionFactory" ref="sessionFactory"></property>
     </bean>
     
     <!-- 创建service实例 -->
     <bean id="deptService" class="xxxx.service.DeptService">
         <property name="deptDao" ref="deptDao"></property>
     </bean>
     
     
     <!-- 
         Spring声明式事务管理配置
      -->
      <!-- a. 事务管理器 -->
      <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
         <property name="sessionFactory" ref="sessionFactory"></property>
      </bean>
      
      <!-- b. 事务通知 -->
      <tx:advice id="txAdvice" transaction-manager="txManager">
         <tx:attributes>
             <tx:method name="*" read-only="false"/>
         </tx:attributes>
      </tx:advice>
      
      <!-- c. Aop配置  = 切入点表达式  + 应用通知规则 -->
      <aop:config>
         <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn..*Service.*(..))"/>
      </aop:config>
     
     
     </beans>     
    
  • Spring对dao操作的支持
    1、直接在dao中使用sessionFactory对象操作数据库
    2、使用Spring提供的 HibernateTemplate 工具类操作数据库,优点: 对session的常用操作进行封装! 比较方便!
    3、(推荐)HibernateDaoSupport工具类 ,Dao类直接继承HibernateDaoSupport工具类即可,HibernateDaoSupport对hibernateTemlate类进行了封装

相关文章

网友评论

      本文标题:Spring小结

      本文链接:https://www.haomeiwen.com/subject/qboczxtx.html