1.引入Spring

  我们在搭建框架时常常会解决问题:对象创建,对象之间依赖关系如何处理,Spring就是来解决这类问题的:控制反转依赖注入

2.环境搭建

  1)下载源码:其中3.0以下版本源码中有Spring相关所有包【核心包+依赖包】

          3.0以上版本源码中只有spring核心包

  2)导入jar包:spring-framework-3.2.5.RELEASE

    commons-logging-1.1.3.jar           日志

    spring-beans-3.2.5.RELEASE.jar        bean节点

    spring-context-3.2.5.RELEASE.jar       spring上下文节点

    spring-core-3.2.5.RELEASE.jar         spring核心功能

    spring-expression-3.2.5.RELEASE.jar    spring表达式相关表

    以上是必须引入的5个jar文件,在项目中可以用户库管理!

  3)核心配置文件applicationContext.xml 和bean的属性描述   

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:p="http://www.springframework.org/schema/p"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context.xsd">
  10.  
  11. </beans>

bean属性描述

  1. /**
  2. * 1) 对象创建: 单例/多例
  3. * scope="singleton", 默认值, 即 默认是单例 【service/dao/工具类】
  4. * scope="prototype", 多例; 【Action对象】
  5. *
  6. * 2) 什么时候创建?
  7. * scope="prototype" 在用到对象的时候,才创建对象。
  8. * scope="singleton" 在启动(容器初始化之前), 就已经创建了bean,且整个应用只有一个。
  9. * 3)是否延迟创建
  10. * lazy-init="false" 默认为false, 不延迟创建,即在启动时候就创建对象
  11. * lazy-init="true" 延迟初始化, 在用到对象的时候才创建对象
  12. * (只对单例有效)
  13. * 4) 创建对象之后,初始化/销毁
  14. * init-method="init_user" 【对应对象的init_user方法,在对象创建爱之后执行 】
  15. * destroy-method="destroy_user" 【在调用容器对象的destriy方法时候执行,(容器用实现类)】
  16. */
  17. @Test
  18. public void testIOC() throws Exception {
  19. // 得到IOC容器对象 【用实现类,因为要调用销毁的方法】
  20. ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/a_hello/applicationContext.xml");
  21. System.out.println("-----容器创建-----");
  22.  
  23. // 从容器中获取bean
  24. User user1 = (User) ac.getBean("user");
  25. User user2 = (User) ac.getBean("user");
  26.  
  27. System.out.println(user1);
  28. System.out.println(user2);
  29.  
  30. // 销毁容器对象
  31. ac.destroy();
  32. }

  4)获取IOC两种方式:

    通过BeanFactory获得IOC容器

  1. // 现在,把对象的创建交给spring的IOC容器
  2. Resource resource = new ClassPathResource("cn/itcast/a_hello/applicationContext.xml");
  3. // 创建容器对象(Bean的工厂), IOC容器 = 工厂类 + applicationContext.xml
  4. BeanFactory factory = new XmlBeanFactory(resource);
  5. // 得到容器创建的对象
  6. User user = (User) factory.getBean("user");

    直接获得IOC容器:ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/a_hello/applicationContext.xml");

  1. //2. (方便)直接得到IOC容器对象
  2. @Test
  3. public void testAc() throws Exception {
  4. // 得到IOC容器对象
  5. ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/a_hello/applicationContext.xml");
  6. // 从容器中获取bean
  7. User user = (User) ac.getBean("user");
  8.  
  9. System.out.println(user);
  10. }

3.专业术语

  1)侵入式设计:引入框架对现有类结构产生影响struts框架;非侵入式框架:引入框架对现有类结构没有影响

  2)控制反转(Inversion on Control  IOC),依赖注入( dependency injection   DI)

    区别:IOC解决对象创建问题;DI:对象创建完后对对象属性赋值,对象间关系依赖的处理【通过set方法依赖注入】

  3)AOP:面向切面编程:切面简单来说就是由很多重复代码组成,如:事务,日志,权限

4.Spring提供的一站式解决方法

  1) Spring Core  spring的核心功能: IOC容器, 解决对象创建及依赖关系

  2) Spring Web  Spring对web模块的支持。

    1. 可以与struts整合,让struts的action创建交给spring

    2. spring mvc模式

  3) Spring DAO  Spring 对jdbc操作的支持  【JdbcTemplate模板工具类】

  4) Spring ORM  spring对orm的支持:

    1. 既可以与hibernate整合,【session】

    2. 也可以使用spring的对hibernate操作的封装

  5)Spring AOP  切面编程

  6)SpringEE   spring 对javaEE其他模块的支持

5.与applicationContext.xml配置文件有关的配置

  1)配置创建对象的三种方式:

    调用无参数构造器;带参数构造器constructor-arg;工厂创建对象factory-bean(静态方法创建对象,非静态方法创建对象)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context.xsd">
  11.  
  12. <!-- ###############对象创建############### -->
  13.  
  14. <!-- . 默认无参数构造器
  15. <bean id="user1" class="cn.itcast.b_create_obj.User"></bean>
  16. -->
  17.  
  18. <!-- . 带参数构造器 -->
  19. <bean id="user2" class="cn.itcast.b_create_obj.User">
  20. <constructor-arg index="" type="int" value=""></constructor-arg>
  21. <constructor-arg index="" type="java.lang.String" value="Jack"></constructor-arg>
  22. </bean>
  23.  
  24. <!-- 定义一个字符串,值是"Jack" ; String s = new String("jack")-->
  25. <bean id="str" class="java.lang.String">
  26. <constructor-arg value="Jacks"></constructor-arg>
  27. </bean>
  28. <bean id="user3" class="cn.itcast.b_create_obj.User">
  29. <constructor-arg index="" type="int" value=""></constructor-arg>
  30. <constructor-arg index="" type="java.lang.String" ref="str"></constructor-arg>
  31. </bean>
  32.  
  33. <!-- . 工厂类创建对象 -->
  34. <!-- # 3.1 工厂类,实例方法 -->
  35. <!-- 先创建工厂 -->
  36. <bean id="factory" class="cn.itcast.b_create_obj.ObjectFactory"></bean>
  37. <!-- 在创建user对象,用factory方的实例方法 -->
  38. <bean id="user4" factory-bean="factory" factory-method="getInstance"></bean>
  39.  
  40. <!-- # 3.2 工厂类: 静态方法 -->
  41. <!--
  42. class 指定的就是工厂类型
  43. factory-method 一定是工厂里面的“静态方法”
  44. -->
  45. <bean id="user" class="cn.itcast.b_create_obj.ObjectFactory" factory-method="getStaticInstance"></bean>
  46.  
  47. </beans>

  2)给对象属性赋值(DI 依赖注入)    

    1.通过构造方法;2.通过set方式;3.p名称空间;4.自动装配;5.注解

    1.通过set方式:bean中加入<property name="userDao" ref="userDao">

     内部bean方式:

  1. <!-- ##############内部bean############## -->
  2. <bean id="userAction" class="cn.itcast.c_property.UserAction">
  3. <property name="userService">
  4. <bean class="cn.itcast.c_property.UserService">
  5. <property name="userDao">
  6. <bean class="cn.itcast.c_property.UserDao"></bean>
  7. </property>
  8. </bean>
  9. </property>
  10. </bean>

    2.p名称空间:p:userDao-ref=""代替了<property>set配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context.xsd">
  11.  
  12. <!-- ###############对象属性赋值############### -->
  13.  
  14. <!--
  15. 给对象属性注入值:
  16. # p 名称空间给对象的属性注入值
  17. (spring3.0以上版本才支持)
  18. -->
  19. <bean id="userDao" class="cn.itcast.c_property.UserDao"></bean>
  20.  
  21. <bean id="userService" class="cn.itcast.c_property.UserService" p:userDao-ref="userDao"></bean>
  22.  
  23. <bean id="userAction" class="cn.itcast.c_property.UserAction" p:userService-ref="userService"></bean>
  24.  
  25. <!-- 传统的注入:
  26. <bean id="user" class="cn.itcast.c_property.User" >
  27. <property name="name" value="xxx"></property>
  28. </bean>
  29. -->
  30. <!-- p名称空间优化后 -->
  31. <bean id="user" class="cn.itcast.c_property.User" p:name="Jack0001"></bean>
  32.  
  33. </beans>

    3.自动装配:autowire="byName";autowire="byType"可以在<bean>属性上设置也可以在全局配置在头部default-autowire="byName">   根据名称自动装配(全局)    

  1. <!-- ###############自动装配############### -->
  2. 自动去IOC容器中找与属性名同名的引用的对象,并自动注入
  3. <bean id="userDao" class="cn.itcast.d_auto.UserDao"></bean>
  4. <bean id="userService" class="cn.itcast.d_auto.UserService" autowire="byName"></bean>
  5. <!-- 根据“名称”自动装配: userAction注入的属性,会去ioc容器中自动查找与属性同名的对象 -->
  6. <bean id="userAction"
  7. class="cn.itcast.d_auto.UserAction" autowire="byName"></bean>
  8.  
  9. 全局配置
  10. <?xml version="1.0" encoding="UTF-8"?>
  11. <beans xmlns="http://www.springframework.org/schema/beans"
  12. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  13. xmlns:p="http://www.springframework.org/schema/p"
  14. xmlns:context="http://www.springframework.org/schema/context"
  15. xsi:schemaLocation="
  16. http://www.springframework.org/schema/beans
  17. http://www.springframework.org/schema/beans/spring-beans.xsd
  18. http://www.springframework.org/schema/context
  19. http://www.springframework.org/schema/context/spring-context.xsd" default-autowire="byName"> 根据名称自动装配(全局)
  20.  
  21. <!-- ###############自动装配############### -->
  22. <bean id="userDao" class="cn.itcast.d_auto.UserDao"></bean>
  23. <bean id="userService" class="cn.itcast.d_auto.UserService"></bean>
  24. <bean id="userAction" class="cn.itcast.d_auto.UserAction"></bean>
  25. </beans>
  26.  
  27. 根据类型byType
  28. <?xml version="1.0" encoding="UTF-8"?>
  29. <beans xmlns="http://www.springframework.org/schema/beans"
  30. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  31. xmlns:p="http://www.springframework.org/schema/p"
  32. xmlns:context="http://www.springframework.org/schema/context"
  33. xsi:schemaLocation="
  34. http://www.springframework.org/schema/beans
  35. http://www.springframework.org/schema/beans/spring-beans.xsd
  36. http://www.springframework.org/schema/context
  37. http://www.springframework.org/schema/context/spring-context.xsd" default-autowire="byType">
  38.  
  39. <!-- ###############自动装配############### -->
  40. <bean id="userDao" class="cn.itcast.d_auto.UserDao"></bean>
  41. <bean id="userService" class="cn.itcast.d_auto.UserService"></bean>
  42.  
  43. <!-- 如果根据类型自动装配: 必须确保IOC容器中只有一个该类型的对象 -->
  44. <bean id="userAction" class="cn.itcast.d_auto.UserAction"></bean>
  45.  
  46. <!-- 报错: 因为上面已经有一个该类型的对象,且使用了根据类型自动装配
  47. <bean id="userService_test" class="cn.itcast.d_auto.UserService" autowire="byType"></bean>
  48. -->
  49. </beans>

    总结:pring提供的自动装配主要是为了简化配置; 但是不利于后期的维护   

    4.注解:

    使用步骤:

      1.先引入context名称空间

      xmlns:context="http://www.springframework.org/schema/context"

      2.开始扫描:

      <context:component-scan base-package="cn.itcast.e_anno2"></context:component-scan>

      3.使用注解:通过注解的方式,把对象加入ioc容器

            @Component   指定把一个对象加入IOC容器

          @Repository   作用同@Component; 在持久层使用

          @Service      作用同@Component; 在业务逻辑层使用

          @Controller    作用同@Component; 在控制层使用

          @Resource     属性注入

      例子:

  1. bean.xml
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <beans xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xmlns:context="http://www.springframework.org/schema/context"
  7. xsi:schemaLocation="
  8. http://www.springframework.org/schema/beans
  9. http://www.springframework.org/schema/beans/spring-beans.xsd
  10. http://www.springframework.org/schema/context
  11. http://www.springframework.org/schema/context/spring-context.xsd">
  12.  
  13. <!-- 开启注解扫描 -->
  14. <context:component-scan base-package="cn.itcast.e_anno2"></context:component-scan>
  15.  
  16. <bean id="userDao" class="cn.itcast.e_anno2.UserDao" scope="prototype">
  17. </bean>
  18.  
  19. </beans>
  20.  
  21. Dao
  22. // 把当前对象加入ioc容器
  23. //@Component("userDao") // 相当于bean.xml 【<bean id=userDao class=".." />】
  24.  
  25. //@Component // 加入ioc容器的UserDao对象的引用名称, 默认与类名一样, 且第一个字母小写
  26.  
  27. //@Repository // 在持久层可以选择用这个注解
  28. public class UserDao {
  29.  
  30. public UserDao(){
  31. System.out.println("UserDao.UserDao()");
  32. }
  33.  
  34. public UserDao(int id){
  35. System.out.println("UserDao.UserDao(int id)" + id);
  36. }
  37.  
  38. public void save() {
  39. System.out.println("DB:保存用户!!!");
  40. }
  41. }
  42.  
  43. Service
  44. //@Component("userService") // userService加入ioc容器
  45.  
  46. //@Component
  47.  
  48. @Service // 表示业务逻辑层的组件
  49. public class UserService {
  50.  
  51. // @Resource // 根据类型查找 【在容器中要确保该类型只有一个变量】
  52.  
  53. @Resource(name = "userDao") // 根据名称查找
  54. private UserDao userDao; // 去容器中招UserDao类型的变量,找到后就赋值
  55.  
  56. public void save() {
  57. userDao.save();
  58. }
  59. }
  60.  
  61. Action
  62. //@Component("userAction") // 加入IOC容器
  63.  
  64. //@Component
  65.  
  66. @Controller // 控制层的组件
  67. public class UserAction {
  68.  
  69. @Resource
  70. private UserService userService;
  71.  
  72. public String execute() {
  73. userService.save();
  74. return null;
  75. }
  76. }

6.Spring与Struts结合

  关键点:struts的action创建交给spring

  导入jar包

  配置xml:Struts.xml;bean.xml;web.xml

    struts.xml:struts路径与action映射配置

    bean.xml:spring ioc 配置

    web.xml:核心过滤器,初始化spring ioc容器

将Spring配置到web.xml中

  1. <!-- 2. spring 配置 -->
  2. <context-param>
  3. <param-name>contextConfigLocation</param-name>
  4. <param-value>/WEB-INF/classes/bean-*.xml</param-value>
  5. </context-param>
  6. <listener>
  7. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  8. </listener>

-----------------------------------------------------------

1.代理模式

  1)理解:代理(Proxy)是一种设计模式,想在目标对象上实现功能扩展可用代理,是用户访问目标对象另一种访问方式

      举例:明星《--经纪人<--用户:另一种方式访问对象给对象添加新功能

  2)静态代理

    1.原理:代理对象实现目标对象一样的接口也可以添加额外功能

    2.优缺点:可以在不改变目标对象功能前提下,对目标对象功能扩展;但是可能会有很多代理的对象,且代理对象和目标对象都要维护

    3.实现方式:与目标对象实现相同接口,在代理对象中添加自己的功能写上目标对象功能--------与装饰者设计模式类似

    4.例子:保存用户(模拟)-》Dao(直接保存)-》DaoProxy(给保存添加事务处理)

  1. IUserDao
  2. package 代理.a_static;
  3.  
  4. public interface IUserDao {
  5. void save();
  6. }
  7. UserDao
  8. package 代理.a_static;
  9.  
  10. public class UserDao implements IUserDao{
  11.  
  12. @Override
  13. public void save() {
  14. System.out.println("用户保存对象");
  15. }
  16.  
  17. }
  18. UserDaoProxy
  19. package 代理.a_static;
  20.  
  21. public class UserDaoProxy implements IUserDao{
  22. private IUserDao target;
  23. public UserDaoProxy(IUserDao target){
  24. this.target=target;
  25. }
  26. @Override
  27. public void save() {
  28. System.out.println("事务开始");
  29. target.save();
  30. System.out.println("事务结束");
  31. }
  32.  
  33. }
  34. 测试APP
  35. package 代理.a_static;
  36.  
  37. public class App {
  38. public static void main(String[] args){
  39. //目标对象
  40. IUserDao target=new UserDao();
  41. //代理对象
  42. IUserDao proxy=new UserDaoProxy(target);
  43. proxy.save();
  44. }
  45. }

  3)动态代理

    1.原理:代理对象不需要实现接口,而是动态的在内存中构建代理对象(需要我们提供代理对象/目标对象 实现接口的类型

    2.核心API:Proxy代理对象工具类

            static Object newProxyInstance(

            ClassLoader loader,       指定当前目标对象使用类加载器

            Class<?>[] interfaces,     目标对象实现的接口的类型

            InvocationHandler h       事件处理器

    3.动态代理总结:代理对象不需要实现接口,但是目标对象必须实现接口,但是遇到目标对象没有实现接口就要用到新技术Cglib代理

    4.例子:

  1. IUserDao
  2. package 代理.b_dynamic;
  3.  
  4. public interface IUserDao {
  5. void save();
  6. }
  7. UserDao
  8. package 代理.b_dynamic;
  9.  
  10. public class UserDao implements IUserDao{
  11.  
  12. @Override
  13. public void save() {
  14. System.out.println("-------用户已保存-------");
  15. }
  16.  
  17. }
  18. 代理对象动态创建,需要提供目标对象
  19. package 代理.b_dynamic;
  20.  
  21. import java.lang.reflect.InvocationHandler;
  22. import java.lang.reflect.Method;
  23. import java.lang.reflect.Proxy;
  24. /**
  25. * 给所有的到创建代理对象【动态代理】
  26. *
  27. * 代理对象不需要实现接口,内存内部自己自动生成
  28. * @author Administrator
  29. *
  30. */
  31. public class ProxyFactory {
  32. private Object target;
  33. public ProxyFactory(Object target){
  34. this.target=target;
  35. }
  36. //内存自动生成的
  37. public Object getProxyInstance(){
  38. return Proxy.newProxyInstance(
  39. //目标对象类加载器
  40. target.getClass().getClassLoader(),
  41. //目标对象实现的接口类型
  42. target.getClass().getInterfaces(),
  43. //核心事务处理器
  44. new InvocationHandler() {
  45. @Override
  46. public Object invoke(Object proxy, Method method, Object[] args)
  47. throws Throwable {
  48. System.out.println("事务开始");
  49.  
  50. //执行目标对象方法
  51. Object returnValue=method.invoke(target, args);//调用目标对象的方法
  52. System.out.println("事务结束");
  53. return returnValue;
  54. }
  55. }
  56. );
  57. }
  58. }
  59. 测试App
  60. package 代理.b_dynamic;
  61.  
  62. public class App {
  63. public static void main(String[] args){
  64. //目的对象
  65. IUserDao target=new UserDao();
  66. //动态代理对象创建
  67. IUserDao proxy=(IUserDao) new ProxyFactory(target).getProxyInstance();
  68. //内存中动态代理对象就是$Proxy0
  69. System.out.println(proxy.getClass());
  70.  
  71. //执行方法
  72. proxy.save();
  73. }
  74.  
  75. }

  4)Cglib代理:子类代理

    1.原理:在内存中构建一个子类对象从而实现对目标对象功能扩展;

        底层原理:通过小儿快的字节码处理框架ASM,来转换字节码生产新类

    2.引入:普通jdk动态代理必须目标对象有接口实现,当遇到没有接口的就需要用CGLIB了

    3.使用步骤:

      1)引入cglib-jar,spring核心包中有了

      2)开始动态在内存中构建子类

      3)代理的类不能为final,否则报错;目标对象的方法如果为final/staic,那么就不会被拦截,不会执行目标对象额外的业务方法

  总结:在Spring的AOP编程中,如果容器的目标对象有实现接口,用JDK代理,没有实现接口可以用cglib子类代理

    4.例子:

    实现MethodInterceptor接口实现逻辑代码-》写获得子代理对象getProxyInsance()->通过Enhancer工具类赋值父类,创建子类代理对象

  1. UserDao
  2. package h_cglib;
  3.  
  4. public class UserDao {
  5. public void save(){
  6. System.out.println("User保存");
  7. }
  8. }
  9. Proxy
  10. package h_cglib;
  11.  
  12. import java.lang.reflect.Method;
  13.  
  14. import org.springframework.cglib.proxy.Enhancer;
  15. import org.springframework.cglib.proxy.MethodInterceptor;
  16. import org.springframework.cglib.proxy.MethodProxy;
  17.  
  18. public class ProxyFactory implements MethodInterceptor{
  19. private Object target;
  20. public ProxyFactory(Object target){
  21. this.target=target;
  22. }
  23. //给目标创建代理自对象
  24. public Object getProxyInsance(){
  25. //1.工具类
  26. Enhancer en=new Enhancer();
  27. //2.设置父类
  28. en.setSuperclass(target.getClass());
  29. //3.设置回调函数
  30. en.setCallback(this);
  31. //4.创建子类(代理对象)
  32. return en.create();
  33. }
  34. @Override
  35. public Object intercept(Object obj, Method method, Object[] args,
  36. MethodProxy arg3) throws Throwable {
  37. // TODO Auto-generated method stub
  38. System.out.println("开始事务。。。");
  39. Object returnValue=method.invoke(target, args);
  40. System.out.println("提交事务。。。");
  41. return returnValue;
  42. }
  43.  
  44. }
  45. 测试类
  46. package h_cglib;
  47.  
  48. import g_dynamic.IUserDao;
  49.  
  50. public class App {
  51.  
  52. public static void main(String[] args) {
  53. //目标对象
  54. UserDao target=new UserDao();
  55. System.out.println(target.getClass());
  56.  
  57. //代理子对象
  58. UserDao proxy=(UserDao) new ProxyFactory(target).getProxyInsance();
  59. proxy.save();
  60. }
  61. }

2.手动实现AOP编程【代码模式】面向切面编程

  1)理解:切片编程,就是将重复代码拿出来放在一个切边类中,之后再和核心逻辑代码组合叫AOP编程

  2)代码例子:都时抽象出重复代码放在AOP切片类中

  1. IUserDao
  2. package e_AOP.myAOP2;
  3.  
  4. public interface IUserDao {
  5. void save();
  6. }
  7. UserDao
  8. package e_AOP.myAOP2;
  9.  
  10. import org.springframework.stereotype.Component;
  11.  
  12. @Component
  13. public class UserDao implements IUserDao{
  14.  
  15. @Override
  16. public void save() {
  17. System.out.println("User保存");
  18. }
  19.  
  20. }
  21. ProxyFactory
  22. package e_AOP.myAOP2;
  23.  
  24. import java.lang.reflect.InvocationHandler;
  25. import java.lang.reflect.Method;
  26. import java.lang.reflect.Proxy;
  27.  
  28. public class ProxyFactory {
  29. private static Object target;
  30. private static Aop aop;
  31.  
  32. public static Object getProxyInstance(Object target_,Aop aop_){
  33. target=target_;
  34. aop=aop_;
  35.  
  36. return Proxy.newProxyInstance(
  37. target.getClass().getClassLoader(),
  38. target.getClass().getInterfaces(),
  39. new InvocationHandler() {
  40.  
  41. @Override
  42. public Object invoke(Object proxy, Method method, Object[] args)
  43. throws Throwable {
  44. aop.begin();
  45. Object returnValue=method.invoke(target, args);
  46. aop.end();
  47. return returnValue;
  48. }
  49. });
  50.  
  51. }
  52. }
  53. Aop
  54. package e_AOP.myAOP2;
  55.  
  56. import org.springframework.stereotype.Component;
  57. /**
  58. * 切片代码,与逻辑代码分离
  59. * @author Administrator
  60. *
  61. */
  62. @Component
  63. public class Aop {
  64. public void begin(){
  65. System.out.println("开始事务。。。");
  66. }
  67. public void end(){
  68. System.out.println("结束事务。。。");
  69. }
  70. }
  71. App
  72. package e_AOP.myAOP2;
  73.  
  74. import org.junit.Test;
  75. import org.springframework.context.ApplicationContext;
  76. import org.springframework.context.support.ClassPathXmlApplicationContext;
  77.  
  78. public class App {
  79. ApplicationContext ac=new ClassPathXmlApplicationContext("e_AOP/myAOP2/bean.xml");
  80. @Test
  81. public void test(){
  82. IUserDao proxy=(IUserDao) ac.getBean("userDao_proxy");
  83. proxy.save();
  84.  
  85. }
  86. }
  87. bean.xml
  88. <?xml version="1.0" encoding="UTF-8"?>
  89. <beans xmlns="http://www.springframework.org/schema/beans"
  90. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  91. xmlns:p="http://www.springframework.org/schema/p"
  92. xmlns:context="http://www.springframework.org/schema/context"
  93. xsi:schemaLocation="
  94. http://www.springframework.org/schema/beans
  95. http://www.springframework.org/schema/beans/spring-beans.xsd
  96. http://www.springframework.org/schema/context
  97. http://www.springframework.org/schema/context/spring-context.xsd">
  98.  
  99. <!-- 开启注解扫描 -->
  100. <context:component-scan base-package="e_AOP.myAOP2.ProxyFactory" ></context:component-scan>
  101.  
  102. <!-- 调用工厂类静态方法放回UserDao 代理后的对象 -->
  103. <bean id="userDao_proxy" class="e_AOP.myAOP2.ProxyFactory" factory-method="getProxyInstance">
  104. <constructor-arg index="" ref="userDao"></constructor-arg>
  105. <constructor-arg index="" ref="aop"></constructor-arg>
  106. </bean>
  107.  
  108. </beans>

3.AOP编程

  1)关键字

    AOP: aspect object programming  面向切面编程,关注点代码与业务代码分离!

    关注点:重复代码

    切面:关注点组成的类

    切入点:执行目标对象方法,动态植入切面代码

        可以通过切入点表达式,指定拦截哪些类的哪些方法,给指定的类在运行时候植入切面类代码

  2)步骤

    1.引入aop的jar包  (aspectj aop优秀组件)

      spring-aop-3.2.5.RELEASE.jar   【spring3.2源码】

      aopalliance.jar   【spring2.5源码/lib/aopalliance】

      aspectjweaver.jar   【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】

      aspectjrt.jar   【spring2.5源码/lib/aspectj】或【aspectj-1.8.2\lib】

    2.bean.xml中引入aop名称空间

xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

    3.开始aop注解

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:aop="http://www.springframework.org/schema/aop"
  7. xsi:schemaLocation="
  8. http://www.springframework.org/schema/beans
  9. http://www.springframework.org/schema/beans/spring-beans.xsd
  10. http://www.springframework.org/schema/context
  11. http://www.springframework.org/schema/context/spring-context.xsd
  12. http://www.springframework.org/schema/aop
  13. http://www.springframework.org/schema/aop/spring-aop.xsd">
  14.  
  15. <!-- 开启注解扫描 -->
  16. <context:component-scan base-package="cn.itcast.e_aop_anno"></context:component-scan>
  17.  
  18. <!-- 开启aop注解方式 -->
  19. <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  20. </beans>

    4.使用注解

  1. 切入点表达式:返回类型+包名+访问的类+类的方法(* cn.itcast.e_aop_anno.*.*(..))
  1.  
  2. @Aspect 指定一个类为切面类
  3. @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式
  4.  
  5. @Before("pointCut_()") 前置通知: 目标方法之前执行
  6. @After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
  7. @AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
  8. @AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
  9. @Around("pointCut_()") 环绕通知: 环绕目标方法执行

    5.例子:

  1. package e_AOP.myAOPanno1;
  2.  
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.After;
  5. import org.aspectj.lang.annotation.AfterReturning;
  6. import org.aspectj.lang.annotation.AfterThrowing;
  7. import org.aspectj.lang.annotation.Around;
  8. import org.aspectj.lang.annotation.Aspect;
  9. import org.aspectj.lang.annotation.Before;
  10. import org.aspectj.lang.annotation.Pointcut;
  11. import org.springframework.stereotype.Component;
  12.  
  13. @Component
  14. @Aspect //指定当前面为切面类
  15. public class Aop {
  16. //指定切入点表单式:拦截表达式,返回类型+包+哪一类+类方法(有参数可以写参数没有..)
  17. @Pointcut("execution(* e_AOP.myAOPanno1.*.*(..))")
  18. public void pointCut_(){
  19.  
  20. }
  21. //前置通知:在执行目标方法之前执行
  22. @Before("pointCut_()")
  23. public void begin(){
  24. System.out.println("开始事务/异常");
  25. }
  26. //后置通知:在执行目标方法之后执行
  27. @After("pointCut_()")
  28. public void after(){
  29. System.out.println("提交事务/关闭");
  30. }
  31. //返回后通知:在调用目标方法之后执行
  32. @AfterReturning("pointCut_()")
  33. public void afterRunning(){
  34. System.out.println("afterRunning()");
  35. }
  36. //异常执行
  37. @AfterThrowing("pointCut_()")
  38. public void afterThrowing(){
  39. System.out.println("afterThrowing()");
  40. }
  41. //环绕执行
  42. @Around("pointCut_()")
  43. public void around(ProceedingJoinPoint pjp) throws Throwable{
  44. System.out.println("环绕前...");
  45. pjp.proceed();//执行目标方法
  46. System.out.println("环绕后...");
  47.  
  48. }
  49. }

测试类

  1. package e_AOP.myAOPanno1;
  2.  
  3. import org.junit.Test;
  4. import org.springframework.context.ApplicationContext;
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;
  6.  
  7. public class App {
  8. ApplicationContext ac =
  9. new ClassPathXmlApplicationContext("e_AOP/myAOPanno1/bean.xml");
  10. // 目标对象有实现接口,spring会自动选择“JDK代理”
  11. @Test
  12. public void testApp() {
  13. IUserDao userDao = (IUserDao) ac.getBean("userDao");
  14. System.out.println(userDao.getClass());//$Proxy001
  15. userDao.save();
  16. }
  17. //目标对象没有实现接口,spring会用“cglib代理”
  18. @Test
  19. public void testCglib(){
  20. OrderDao orderDao=(OrderDao) ac.getBean("orderDao");
  21. System.out.println(orderDao.getClass());
  22. orderDao.save();
  23. }
  24. }

全部配置在bean.xml中

  1. <!-- 配置OrderDao -->
  2. <bean id="userDao" class="e_AOP.myAOXml.UserDao"></bean>
  3. <!-- 配置UserDao -->
  4. <bean id="orderDao" class="e_AOP.myAOXml.OrderDao"></bean>
  5. <!-- 配置Aop -->
  6. <bean id="aop" class="e_AOP.myAOXml.Aop"></bean>
  7. <!-- Aop配置-->
  8. <aop:config>
  9. <!-- 定义一个切入点表达式:拦截哪些方法 -->
  10. <aop:pointcut expression="execution(* e_AOP.myAOXml.*.*(..))" id="pt"/>
  11. <!-- 切面 -->
  12. <aop:aspect ref="aop">
  13. <!-- 环绕通知 -->
  14. <aop:around method="around" pointcut-ref="pt"/>
  15. <!-- 前置通知: 在目标方法调用前执行 -->
  16. <aop:before method="begin" pointcut-ref="pt"/>
  17. <!-- 后置通知: -->
  18. <aop:after method="after" pointcut-ref="pt"/>
  19. <!-- 返回后通知 -->
  20. <aop:after-returning method="afterReturning" pointcut-ref="pt"/>
  21. <!-- 异常通知 -->
  22. <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
  23. </aop:aspect>
  24. </aop:config>

切面类的所有配置

  1. <!-- 切面类 -->
  2. <bean id="aop" class="cn.itcast.g_pointcut.Aop"></bean>
  3.  
  4. <!-- Aop配置 -->
  5. <aop:config>
  6.  
  7. <!-- 定义一个切入点表达式: 拦截哪些方法 -->
  8. <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>-->
  9.  
  10. <!-- 【拦截所有public方法】 -->
  11. <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
  12.  
  13. <!-- 【拦截所有save开头的方法 】 -->
  14. <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
  15.  
  16. <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
  17. <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->
  18.  
  19. <!-- 【拦截指定类的所有方法】 -->
  20. <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->
  21.  
  22. <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
  23. <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
  24.  
  25. <!-- 【多个表达式】 -->
  26. <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
  27. <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
  28. <!-- 下面2个且关系的,没有意义 -->
  29. <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) &amp;&amp; execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
  30. <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
  31.  
  32. <!-- 【取非值】 -->
  33. <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
  34. <aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>
  35.  
  36. <!-- 切面 -->
  37. <aop:aspect ref="aop">
  38. <!-- 环绕通知 -->
  39. <aop:around method="around" pointcut-ref="pt"/>
  40. </aop:aspect>
  41. </aop:config>

4.Spring DAO

  类似于DbUtil

  1)配置xml导入JdbcTemplate对象

  1. <!-- 1. 数据源对象: C3P0连接池 -->
  2. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  3. <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
  4. <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property>
  5. <property name="user" value="root"></property>
  6. <property name="password" value="root"></property>
  7. <property name="initialPoolSize" value="3"></property>
  8. <property name="maxPoolSize" value="10"></property>
  9. <property name="maxStatements" value="100"></property>
  10. <property name="acquireIncrement" value="2"></property>
  11. </bean>
  12.  
  13. <!-- 2. 创建JdbcTemplate对象 -->
  14. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  15. <property name="dataSource" ref="dataSource"></property>
  16. </bean>
  17.  
  18. <!-- dao 实例 -->
  19. <bean id="userDao" class="cn.itcast.h_jdbc.UserDao">
  20. <property name="jdbcTemplate" ref="jdbcTemplate"></property>
  21. </bean>

  2)使用这个JdbcTemplate对象

  1. private JdbcTemplate jdbcTemplate;
  2. public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  3. this.jdbcTemplate = jdbcTemplate;
  4. }
  5.  
  6. public void save() {
  7. String sql = "insert into t_dept(deptName) values('test');";
  8. jdbcTemplate.update(sql);
  9. }
  10.  
  11. public Dept findById(int id) {
  12. String sql = "select * from t_dept where deptId=?";
  13. List<Dept> list = jdbcTemplate.query(sql,new MyResult(), id);
  14. return (list!=null && list.size()>0) ? list.get(0) : null;
  15. }
  16.  
  17. public List<Dept> getAll() {
  18. String sql = "select * from t_dept";
  19. List<Dept> list = jdbcTemplate.query(sql, new MyResult());
  20. return list;
  21. }
  22.  
  23. class MyResult implements RowMapper<Dept>{
  24.  
  25. // 如何封装一行记录
  26. @Override
  27. public Dept mapRow(ResultSet rs, int index) throws SQLException {
  28. Dept dept = new Dept();
  29. dept.setDeptId(rs.getInt("deptId"));
  30. dept.setDeptName(rs.getString("deptName"));
  31. return dept;
  32. }
  33.  
  34. }

5.Spring事务管理

    1).事务管理分类

      1.编程式事务管理:是jdbc中conn.setAutoCommite(false)

               Hibernate中是session.beginTransaction()

               细粒度的事务控制

      2.声明式事务管理:只需在配置文件中配置,实现了对事务控制最大解耦

               Jdbc:DataSourceTransactionManager

                Hibernate技术:HibernateTransactionManager

                粗粒度事务控制:只能给整个方法应用事务,因为aop拦截的是方法

    2)配置事务管理

      1.引入spring-aop相关4个jar文件;2.引入aop名称空间3.引入tx名称空间

      2.spring声明式事务管理配置:

          1)配置事务管理器类2)配置事务增强如何管理事务3)AOP配置拦截哪些方法应用上面的增强

  1. <!-- #############5. Spring声明式事务管理配置############### -->
  2. <!-- 5.1 配置事务管理器类 -->
  3. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  4. <property name="dataSource" ref="dataSource"></property>
  5. </bean>
  6.  
  7. <!-- 5.2 配置事务增强(如果管理事务?) -->
  8. <tx:advice id="txAdvice" transaction-manager="txManager">
  9. <tx:attributes>
  10. <tx:method name="get*" read-only="true"/>
  11. <tx:method name="find*" read-only="true"/>
  12. <tx:method name="*" read-only="false"/>
  13. </tx:attributes>
  14. </tx:advice>
  15.  
  16. <!-- 5.3 Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
  17. <aop:config>
  18. <aop:pointcut expression="execution(* cn.itcast.a_tx.DeptService.*())" id="pt"/>
  19. <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
  20. </aop:config>

    3)完整例子

  1. 1. DeptDao.java
  2. public class DeptDao {
  3.  
  4. // 容器注入JdbcTemplate对象
  5. private JdbcTemplate jdbcTemplate;
  6. public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  7. this.jdbcTemplate = jdbcTemplate;
  8. }
  9.  
  10. public void save(Dept dept){
  11. String sql = "insert into t_dept (deptName) values(?)";
  12. jdbcTemplate.update(sql,dept.getDeptName());
  13. }
  14. }
  15.  
  16. 2. DeptService
  17. public class DeptService {
  18.  
  19. // 容器注入dao对象
  20. private DeptDao deptDao;
  21. public void setDeptDao(DeptDao deptDao) {
  22. this.deptDao = deptDao;
  23. }
  24.  
  25. /*
  26. * 事务控制?
  27. */
  28. public void save(Dept dept){
  29. // 第一次调用
  30. deptDao.save(dept);
  31.  
  32. int i = 1/0; // 异常: 整个Service.save()执行成功的要回滚
  33.  
  34. // 第二次调用
  35. deptDao.save(dept);
  36. }
  37. }
  38. 3. App 测试类
  39. @Test
  40. public void testApp() throws Exception {
  41. //容器对象
  42. ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/a_tx/bean.xml");
  43.  
  44. // 模拟数据
  45. Dept dept = new Dept();
  46. dept.setDeptName("测试: 开发部");
  47.  
  48. DeptService deptService = (DeptService) ac.getBean("deptService");
  49. deptService.save(dept);
  50.  
  51. }
  52. 4. bean.xml (Spring声明式事务管理配置)
  53. <?xml version="1.0" encoding="UTF-8"?>
  54. <beans xmlns="http://www.springframework.org/schema/beans"
  55. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  56. xmlns:p="http://www.springframework.org/schema/p"
  57. xmlns:context="http://www.springframework.org/schema/context"
  58. xmlns:aop="http://www.springframework.org/schema/aop"
  59. xmlns:tx="http://www.springframework.org/schema/tx"
  60. xsi:schemaLocation="http://www.springframework.org/schema/beans
  61. http://www.springframework.org/schema/beans/spring-beans.xsd
  62. http://www.springframework.org/schema/context
  63. http://www.springframework.org/schema/context/spring-context.xsd
  64. http://www.springframework.org/schema/aop
  65. http://www.springframework.org/schema/aop/spring-aop.xsd
  66. http://www.springframework.org/schema/tx
  67. http://www.springframework.org/schema/tx/spring-tx.xsd">
  68.  
  69. <!-- 1. 数据源对象: C3P0连接池 -->
  70. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  71. <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
  72. <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property>
  73. <property name="user" value="root"></property>
  74. <property name="password" value="root"></property>
  75. <property name="initialPoolSize" value="3"></property>
  76. <property name="maxPoolSize" value="10"></property>
  77. <property name="maxStatements" value="100"></property>
  78. <property name="acquireIncrement" value="2"></property>
  79. </bean>
  80.  
  81. <!-- 2. JdbcTemplate工具类实例 -->
  82. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  83. <property name="dataSource" ref="dataSource"></property>
  84. </bean>
  85.  
  86. <!-- 3. dao实例 -->
  87. <bean id="deptDao" class="cn.itcast.a_tx.DeptDao">
  88. <property name="jdbcTemplate" ref="jdbcTemplate"></property>
  89. </bean>
  90.  
  91. <!-- 4. service实例 -->
  92. <bean id="deptService" class="cn.itcast.a_tx.DeptService">
  93. <property name="deptDao" ref="deptDao"></property>
  94. </bean>
  95.  
  96. <!-- #############5. Spring声明式事务管理配置############### -->
  97. <!-- 5.1 配置事务管理器类 -->
  98. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  99. <property name="dataSource" ref="dataSource"></property>
  100. </bean>
  101.  
  102. <!-- 5.2 配置事务增强(如果管理事务?) -->
  103. <tx:advice id="txAdvice" transaction-manager="txManager">
  104. <tx:attributes>
  105. <tx:method name="get*" read-only="true"/>
  106. <tx:method name="find*" read-only="true"/>
  107. <tx:method name="*" read-only="false"/>
  108. </tx:attributes>
  109. </tx:advice>
  110.  
  111. <!-- 5.3 Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
  112. <aop:config>
  113. <aop:pointcut expression="execution(* cn.itcast.a_tx.DeptService.*())" id="pt"/>
  114. <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
  115. </aop:config>
  116.  
  117. </beans>

       3.注解方式实现事务管理

注解声明讲解:

  1. 事物传播行为介绍:
  2. @Transactional(propagation=Propagation.REQUIRED)
  3. 如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
  4. @Transactional(propagation=Propagation.NOT_SUPPORTED)
  5. 容器不为这个方法开启事务
  6. @Transactional(propagation=Propagation.REQUIRES_NEW)
  7. 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
  8. @Transactional(propagation=Propagation.MANDATORY)
  9. 必须在一个已有的事务中执行,否则抛出异常
  10. @Transactional(propagation=Propagation.NEVER)
  11. 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
  12. @Transactional(propagation=Propagation.SUPPORTS)
  13. 如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
  14.  
  15. 事物超时设置:
  16. @Transactional(timeout=) //默认是30秒
  17.  
  18. 事务隔离级别:
  19. @Transactional(isolation = Isolation.READ_UNCOMMITTED)
  20. 读取未提交数据(会出现脏读, 不可重复读) 基本不使用
  21. @Transactional(isolation = Isolation.READ_COMMITTED)
  22. 读取已提交数据(会出现不可重复读和幻读)
  23. @Transactional(isolation = Isolation.REPEATABLE_READ)
  24. 可重复读(会出现幻读)
  25. @Transactional(isolation = Isolation.SERIALIZABLE)
  26. 串行化
  27.  
  28. MYSQL: 默认为REPEATABLE_READ级别
  29. SQLSERVER: 默认为READ_COMMITTED
  30.  
  31. 脏读 : 一个事务读取到另一事务未提交的更新数据
  32. 不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说,
  33. 后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
  34. 读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
  35. 幻读 : 一个事务读到另一个事务已提交的insert数据
  36.  
  37. @Transactional注解中常用参数说明
  38.  
  39.  
  40.  
  41. readOnly
  42.  
  43. 该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true)
  44.  
  45. rollbackFor
  46.  
  47. 该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:
  48.  
  49. 指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
  50.  
  51. 指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
  52.  
  53. 续表)
  54.  
  55.  
  56.  
  57. rollbackForClassName
  58.  
  59. 该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:
  60.  
  61. 指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")
  62.  
  63. 指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})
  64.  
  65. noRollbackFor
  66.  
  67. 该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:
  68.  
  69. 指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)
  70.  
  71. 指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
  72.  
  73. noRollbackForClassName
  74.  
  75. 该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:
  76.  
  77. 指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException")
  78.  
  79. 指定多个异常类名称:
  80.  
  81. @Transactional(noRollbackForClassName={"RuntimeException","Exception"})
  82.  
  83. propagation
  84.  
  85. 该属性用于设置事务的传播行为,具体取值可参考表6-。
  86.  
  87. 例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
  88.  
  89. isolation
  90.  
  91. 该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置
  92.  
  93. timeout
  94.  
  95. 该属性用于设置事务的超时秒数,默认值为-1表示永不超时
  96.  
  97. 注意的几点:
  98. @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.
  99.  
  100. 2 spring 事务管理器,由spring来负责数据库的打开,提交,回滚.默认遇到运行期例外(throw new RuntimeException("注释");)会回滚,即遇到不受检查(unchecked)的例外时回滚;而遇到需要捕获的例外(throw new Exception("注释");)不会回滚,即遇到受检查的例外(就是非运行时抛出的异常,编译器会检查到的异常叫受检查例外或说受检查异常)时,需我们指定方式来让事务回滚 要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常}) .如果让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
  101. 如下:
  102. @Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚
  103. public void methodName() {
  104. throw new Exception("注释");
  105.  
  106. }
  107. @Transactional(noRollbackFor=Exception.class)//指定不回滚,遇到运行期例外(throw new RuntimeException("注释");)会回滚
  108. public ItimDaoImpl getItemDaoImpl() {
  109. throw new RuntimeException("注释");
  110. }
  111.  
  112. @Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protectedprivate 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
  113.  
  114. @Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 <tx:annotation-driven/>元素的出现 开启 了事务行为。
  115.  
  116. Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因 此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。

配置文件关于事务管理部分的改为

  1. <!-- 事务管理器类 -->
  2. <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  3. <property name="dataSource" ref="dataSource"></property>
  4. </bean>
  5.  
  6. <!-- 开启注解扫描 -->
  7. <context:component-scan base-package="cn.itcast.b_anno"></context:component-scan>
  8.  
  9. <!-- 注解方式实现事务: 指定注解方式实现事务 -->
  10. <tx:annotation-driven transaction-manager="txManager"/>

调用事务的方法使用注解的用法

  1. @Transactional(
  2. readOnly=false,
  3. timeout=-1,
  4. isolation=Isolation.DEFAULT,
  5. propagation=Propagation.REQUIRED
  6. )
  7. public void save(Dept dept){
  8. //第一次调用
  9. deptDao.save(dept);
  10.  
  11. int i = 1/0; // 异常: 整个Service.save()执行成功的要回滚
  12.  
  13. // 第二次调用
  14. deptDao.save(dept);
  15. }

      4.事务属性

  1. @Transactional(
  2. readOnly = false, // 读写事务
  3. timeout = -1, // 事务的超时时间不限制
  4. noRollbackFor = ArithmeticException.class, // 遇到数学异常不回滚
  5. isolation = Isolation.DEFAULT, // 事务的隔离级别,数据库的默认
  6. propagation = Propagation.REQUIRED // 事务的传播行为
  7. )
  8. public void save(Dept dept){
  9. deptDao.save(dept);
  10. int i = 1/0;
  11. deptDao.save(dept);
  12. }
  13.  
  14. 事务传播行为:
  15. Propagation.REQUIRED
  16. 指定当前的方法必须在事务的环境下执行;
  17. 如果当前运行的方法,已经存在事务, 就会加入当前的事务;
  18. Propagation.REQUIRED_NEW
  19. 指定当前的方法必须在事务的环境下执行;
  20. 如果当前运行的方法,已经存在事务: 事务会挂起; 会始终开启一个新的事务,执行完后; 刚才挂起的事务才继续运行

java深入探究12-框架之Spring的更多相关文章

  1. 【转】Java十大常用框架介绍(spring系+dubbo+RabbitMQ+Ehcache+redis)

    一.SpringMVC Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动 ...

  2. atititt.java定时任务框架选型Spring Quartz 注解总结

    atititt.java定时任务框架选型Spring Quartz 总结 1. .Spring Quartz  (ati recomm) 1 2. Spring Quartz具体配置 2 2.1. 增 ...

  3. java框架篇---spring AOP 实现原理

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  4. Java后端框架之Spring Boot详解,文末有Java分布式实战项目视频可取

    在 Java 后端框架繁荣的今天,Spring 框架无疑是最最火热,也是必不可少的开源框架,更是稳坐 Java 后端框架的龙头老大. 用过 Spring 框架的都知道 Spring 能流行是因为它的两 ...

  5. java框架之Spring(2)-注解配置IOC&AOP配置

    注解配置IoC 准备 1.要使用注解方式配置 IoC,除了之前引入的基础 jar 包,还需要引入 spring-aop 支持包,如下: 2.在 applicationContext.xml 中引入 c ...

  6. Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述

    第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...

  7. Java匹马行天下之J2EE框架开发——Spring—>Spring框架知多少

    ————也许我注定成不了一个伟大的人,但是至少我可以做一个很棒的自己.我想我现在应该做的不是瞻前顾后,而是活在当下,正确认知自己,做好自己现在的工作,努力提升自己的能力,踏踏实实地做一个程序员 一.思 ...

  8. Java - 框架之 Spring

    一. IOC 和 DI IOC : 控制反转,将对象的创建权反转给了 Spring.DI  : 依赖注入,前提是必须要有 IOC 的环境,Spring 管理这个类的时候将类的依赖的属性注入(设置)进来 ...

  9. 深入理解java:4.2. 框架编程之Spring框架的设计理念

    什么是Spring呢? Spring是为了解决企业应用开发的复杂性而创建的一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架. Spring优点 简单了解Spring之后,我们看一下Spri ...

随机推荐

  1. 表变量、临时表(with as ,create table)

    1.declare @t table(CountryRegionCode nvarchar(3))insert into @t(CountryRegionCode)  (select CountryR ...

  2. class 中构造函数与析构函数

    import pymysql class My_sql(): def __init__(self, host, user, passwd, db, port=3306, charset='utf8') ...

  3. ViewPager页面切换特效

    ViewPager页面切换特效如下效果 看效果: 效果1: 效果2: 下面就开始讲解如何实现这两个页面翻转效果 1.首先你得会ViewPager控件的使用(废话!现在还有人不会使用吗???!!) 2. ...

  4. NoSQL-redis with python

    首先,先去看了一下NoSQL的概念: Wiki中参考的NoSQL终极指南(nosql-database.org)中说: NoSQL DEFINITION: Next Generation Databa ...

  5. 【BZOJ4825】[Hnoi2017]单旋 线段树+set

    [BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...

  6. Xamarin.Forms学习之Page Navigation(一)

    在最初接触Xamarin.Forms的时候,我是跟着Xamarin官方的名为“learning-xamarin-ebook”的pdf文档进行学习的,我在成功运行Hello world程序之后,我开始跟 ...

  7. Date、Calendar、DateFormat、SimpleDateFormat、Timer、TimerTask类

    类 Date 在 JDK 1.1 之前,类 Date 有两个其他的函数.它允许把日期解释为年.月.日.小时.分钟和秒值. 它也允许格式化和解析日期字符串.不过,这些函数的 API 不易于实现国际化.从 ...

  8. CSS3 Flex布局(容器)

    一.flex-direction属性 row(默认值):主轴为水平方向,起点在左端. row-reverse:主轴为水平方向,起点在右端. column:主轴为垂直方向,起点在上沿. column-r ...

  9. Hibernate 框架入门(一)

    1. SSH Web 层: Struts2 业务层: Spring 持久层: Hibernate 2. Hibernate 概述 概述 Hibernate 是一个对象关系映射框架(ORM 框架); 对 ...

  10. MariaDB数据库主从复制实现步骤

    一.MariaDB简介 MariaDB数据库的主从复制方案,是其自带的功能,并且主从复制并不是复制磁盘上的数据库文件,而是通过binlog日志复制到需要同步的从服务器上. MariaDB数据库支持单向 ...