Spring学习笔记

在这里插入图片描述Aop 在这里插入图片描述

Spring

  • spring是一个容器
  • spring是一个分层的java ee/(一站式)轻量级开源框架
  • 它不排斥其他框架,还帮其他框架管理对象
  • aop支持
  • ioc思想
  • spring jdbc
  • aop事务
  • junit支持

Spring框架搭建

步骤:

  1. 导包

  2. 创建一个对象

  3. 书写配置,注册对象到容器(配置文件的位置、名称任意,建议方法哦src下,名字为applicationContext.xml);约束引入

    <?xml version="1.0" encoding="UTF-8"?>
    	<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
    	
    
    	<!-- 将User对象交给Spring容器管理 -->
    	<bean name="user" class="com.rabbit.bean.User"></bean>
    </beans>
    
  4. 代码测试

     public void fun1() {
     	//创建容器对象
     	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
     	//向容器“要对象”
     	User u = (User) ac.getBean("user");
     	//打印user对象
     	System.out.println(u);
     }
    

约束引入:

D:\JavaStdNotes\java框架学习\SSH\Spring\spring-day01\spring-day01\video\03-spring项目搭建-约束引入_.flv

Spring概念

思想 :IOC DI

IOC:Inverse Of Control

  • 将我们创建对象的方式反转;以前是对象的创建是由我们开发人员自己维护。包括依赖关系也是自己人注入;
  • 使用了Spring之后,对象的创建以及对象中的依赖关系,可以由Spring完成创建以及注入;
  • 反转控制就是反转了创建对象的方式,从我们自己创建反转给了(程序)Spring;

DI:Dependency Injection (依赖注入)

  • 实现IOC之前需要DI支持;
  • 注入方式:
    • set方法注入
    • 构造方法注入
    • 字段注入
  • 注入类型:
    • 值类型注入:8大基本数据类型
    • 引用类型注入:将依赖对象注入

applicationContext&BeanFactory

BeanFactory接口:

  • Spring 原始接口,针对原始接口的实现功能较为单一
  • BeanFactory接口实现类的容器,特点是每次在获得对象时才会创建对象

ApplicationContext:

  • 每次容器启动时就会创建容器中配置的所有对象
  • 提供了更多功能
  • 实现类:
    • ClassPathXmlApplicationContext;从类路径下加载配置文件(主要使用)
    • FileSystemXMLApplicationContext;从硬盘绝对路径下加载配置文件

结论:在web开发中使用applicationContext;资源匮乏时可以使用BeanFactory

配置文件

Bean元素使用:该元素描述需要搜谱spring容器管理的对象:

  • name属性:给被管理的对象起个名字,过得对象时根据名称获得对象
  • class属性:被管理的对象完整路径名
  • id属性:与name属性一模一样。名称不可重复,并且不能使用特殊字符

三种对象创建方式:

  1. 空参构造创建(常用):

     <!-- 将User对象交给Spring容器管理   空参构造创建-->
     <bean name="user" class="com.rabbit.bean.User"></bean>
    
  2. 静态工厂创建(了解):

     <!-- 2. 静态工创建: 调用UseerFactory的createUser()方法创建名为user2的对象,放入容器-->
     <bean name="user2" class="com.rabbit.Factory.UserFactory" factory-method="createUser"></bean>
    
  3. 实例工厂创建:

     <!-- 3. 实例工厂创建-->
     <bean name="user3" factory-bean="userFactory" factory-method="createUser2"></bean>
     <bean name="userFactory" class="com.rabbit.Factory.UserFactory"></bean>
    

Bean元素进阶:scope属性

  • singleton(重要):默认值为singleton,单例对象,在spring容器中只会存在一个实例;多用singleton
  • prototype(重要):多例原型;被标识为多例的对象每次在获得时才会创建对象;并且每次创建都是一个新的对象;在与struts2整合的时候Action要用prototype;
  • request(了解):web环境下对象与request生命周期一致
  • session(了解):web环境下,对象与session生命周期一致;

Bean元素进阶:生命周期属性(了解)

  • 配置一个方法作为生命周期初始化方法,sprign会在对象创建之后立即调用;init-method
  • 配置一个方法作为生命周期销毁方法,spring容器在关闭前销毁所有容器中的对象;destory-method;

spring的分模块配置:

<!-- 引入其他spring配置文件 路径为去src之后的路径-->
<import resource="/applicationContext.xml"/>

spring属性注入

set方法注入(重点):

<!--set方式注入-->
<bean name="user" class="com.rabbit.bean.User">
	<!-- 值类型注入:为名为name的属性注入tom作为值 -->
	<property name="name" value="tom"></property>
	<property name="age" value="18"></property>
	<!-- 引用类型注入:注入对象 ref;为car属性注入上方的car -->
	<property name="car" ref="car"></property>
</bean>	
	<!-- 将Car对象配置到容器中 -->
	<bean name="car" class="com.rabbit.bean.Car">
		<property name="name" value="兰博基尼"></property>
		<property name="color" value="橘色"></property>
	</bean>

构造函数注入(掌握):

<!-- 构造函数注入 -->
<bean name="user2" class="com.rabbit.bean.User">
	<!-- User 构造函数public User(String name, Car car) -->
	<!-- index为构造函数里面属性所在的索引位置 -->
	<!-- type为构造函数里面属性的类型 -->
	<constructor-arg name="name" value="jerry" index="0" type="java.lang.String"></constructor-arg>
	<constructor-arg name="car" ref="car"></constructor-arg>
</bean>

p名称空间注入(了解):

  • 导入p名称空间:xmlns:p=“http://www.springframework.org/schema/p

  • 使用p:属性完成注入:

      <!-- p名称空间注入 -->
      <bean name="user3" class="com.rabbit.bean.User" p:name="jack" p:age="20" p:car-ref="car"></bean>
    

spel注入:(了解)

<!--spel(Spring expression Language sping)表达式语言注入 -->
<bean name="user4" class="com.rabbit.bean.User">
	<property name="name" value="#{user.name}"></property>
	<property name="age" value="#{user3.age}"></property>
	<property name="car" ref="car"></property>
</bean>

复杂类型注入:




```xml
<!-- 复杂类型注入 -->
	<!-- array数组注入 -->
	<bean name="cbean" class="com.rabbit.bean.CollectionBean">
		<!-- 如果数组中只有一个属性 可以直接value |ref即可-->
		<!-- 如果数组中有多个属性-->
		<property name="arr">
			<array>
				<value>tom</value>
				<value>jerry</value>
				<ref bean="user4"/>
			</array>
		</property>
		<!-- list -->
		<property name="list">
			<list>
				<value>red</value>
				<value>green</value>
				<ref bean="user3"/>
			</list>
		</property>
		<!-- map类型 -->
		<property name="map">

			<map>
				<entry key="url" value="jdbc:mysql:///crm"></entry>
				<entry key="user" value-ref="user4"></entry>
			</map>

		</property>
		<!-- properties类型 -->
		<property name="prop">
			<props>
				<prop key="driverClass">com.jdbc.mysql:Driver</prop>
				<prop key="username">root</prop>
				<prop key="password">admin</prop>
			</props>
		</property>

让spring容器随项目启动而启动,销毁而销毁:web.xml配置文件配置;导入spring-web-4.2.4.RELEASE.jar

  <!-- 让spring容器随项目启动创建,随项目关闭而销毁 -->
  <listener>
  	<listener-class>org.springframework.web.context.ContextLoader</listener-class>
  </listener>
  <!-- 指定加载配置文件的位置 -->
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>classpath:applicationContext.xml</param-value>
  </context-param>

获取spring容器:

	//获得spring容器==》从application域获得即可
	//获得ServletContext对象
	ServletContext sc = ServletActionContext.getServletContext();
	//从sc中获得ac容器
	WebApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sc);
	//从容器获得CustomerService
	CustomerService service = (CustomerService) ac.getBean("customerService");

#使用注解配置spring:导入spring注解依赖包spring-aop-4.2.4.RELEASE.jar #

  1. 为配置文件导入新的命名空间约束

  2. 开启注解代替配置文件

     <!-- 指定扫面com.rabbit.bean包下的所有类中的注解
     		注意:扫描包时会扫描指定包下的所有子孙包
      -->
     <context:component-scan base-package="com.rabbit.bean"></context:component-scan>
    
  3. 使用注解:

     //这4个注解功能没有任何区别
     @Component("user")//domain层
     //<bean name="user" class="com.rabbit.bean.User">
     @Service("user")//用于注册service层
     @Controller("user")//web层
     @Repository("user")//dao层
    
  • 指定对象作用域:

      @Component("user")
      @Scope(scopeName="prototype")//指定对象的作用域,默认为单例的不用写
    
  • 注解指定值类型:可以写在成员变量上(通过反射赋值),也可以写在set方法上(通过set赋值)

      @Component("user")
      public class User {
      	@Value("tom")
      	private String name;
      	private int age;
      	private Car car;
      }
    
  • 引用类型注入方式1:

    • 首先把该对象加入容器

    • 在对象成员变量上加上注解:

        	@Autowired//自动装配:问题:这种方式如果在容器类有多个对象就无法保证能选取哪一个
        	private Car car;
      
    • 解决问题:不建议使用

        	@Autowired
        	@Qualifier("car2")//使用这个注解选择具体的对象在容器中名称
        	private Car car;
      
  • 引用类型注入方式2:推荐使用

      @Resource(name="car2")//手动注入,指定哪个名称的对象
      private Car car;
    
  • 指定方法为初始化,销毁方法:

      @PostConstruct//让该方法为初始化方法;跟配置文件中的init-method一样
      public void init() {
      	System.out.println("初始化");
      }
      @PreDestroy//让该方法为销毁时调用的方法
      public void destory() {
      	System.out.println("销毁");
      }
    

sts插件:配置文件可以有提示


AOP思想 : 面向切面编程

Spring能够为容器中管理的对象生成动态代理对象:

  • spring能够为我们生成代理对象

Spring实现aop原理:

  • 动态代理:

    • 被代理对象必须要实现接口,如果没有接口将不能实现动态代理
  • cglib代理:

    • 带三方代理技术,cglib代理,可以对任何类生成代理。因为代理的原理是对目标对象进行继承代理

AOP名称学习:

  • joinpoint(连接点):目标对象中,所有可以曾强的方法
  • Pointcut(切入点):目标对象,已经增强的方法
  • Advice(通知/增强):增强的代码
  • Target(目标对象):被代理对象
  • Weaving(织入):将通知织入切入点
  • Proxy(代理):将通知织入到目标对象后形成代理对象
  • aspect(切面):切入点+通知

Spring中的AOP演示:

  1. 导包(4+2+2+2)
  2. 准备目标对象
  3. 准备通知
	//通知类
	public class MyAdvice {
	
		//前置通知:目标方法运行之前调用
		//后置通知(如果出现异常,将不会调用):在目标方法运行之后调用
		//环绕通知:在目标方法之前和之后都调用
		//异常拦截通知:如果出现异常,就会调用
		//后置通知(无论是否出现异常都会调用):在目标方法运行之后调用




			//前置通知
			public void before() {
				System.out.println("前置通知");
			}
			
			//后置通知:如果方法出现异常不调用
			public void after() {
				System.out.println("后置通知,异常不调用");
			}
			//环饶通知
			public Object around(ProceedingJoinPoint pjp) throws Throwable {
				System.out.println("环绕通知之前的部分");
				Object proceed = pjp.proceed();//调用目标方法
				System.out.println("环绕通知之后的部分");
				return proceed;
			}
			//异常通知
			public void afterException() {
				System.out.println("出事了之后执行的异常通知");
			}
			//后置通知
			public void after2() {
				System.out.println("出现异常也会调用");
			}
		}
  1. 配置进行织入,将通知织入目标对象

    <?xml version="1.0" encoding="UTF-8"?>
    	<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
    	<!-- 准备工作:导入aop约束命名空间 -->
    	<!-- 1.配置目标对象 -->
    		<bean name="userServiceTarget" class="com.rabbit.interf.UserServiceImp"></bean>
    	<!-- 2.配置通知类 -->
    		<bean name="myAdvice" class="com.rabbit.spring_aop.MyAdvice"></bean>
    	<!-- 3.配置将通知织入目标对象 -->
    		aop:config
    			<!-- 配置切入点
    				切入表达式expression="execution(public void com.rabbit.interf.UserServiceImp.save())":只增强save()
    							public是默认的,可以不写			void com.rabbit.interf.UserServiceImp.save()
    							返回值任意								* com.rabbit.interf.UserServiceImp.save()
    							任意方法									* com.rabbit.interf.UserServiceImp.*()
    		任意名为xxxServiceImp的任意方法任意参数		* com.rabbit.interf.ServiceImp.(..)				最终形态
    
    - com.rabbit.interf..ServiceImp.(..)				最终形态
    -->
    		<aop:pointcut expression="execution(* com.rabbit.interf.ServiceImp.(..))" id="pc"/>
    		<aop:aspect ref="myAdvice">
    			<!-- 指定名为before的方法为前置通知 -->
    			<aop:before method="before" pointcut-ref="pc"/>
    			<!-- 后置 -->
    			<aop:after-returning method="afterreturning" pointcut-ref="pc"/>
    			<!-- 环绕 -->
    			<aop:around method="around" pointcut-ref="pc"/>
    			<!-- 异常拦截 -->
    			<aop:after-throwing method="afterException" pointcut-ref="pc"/>
    			<!-- 后置 -->
    			<aop:after method="after" pointcut-ref="pc"/>
    		/aop:aspect
    	/aop:config
    </beans>
    
    

测试:这里使用注解获取容器对象UserService:

	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration("classpath:com/rabbit/spring_aop/applicationContext.xml")
	public class Demo1 {
		@Resource(name="userService")
		private UserService us;
		
		@Test
		public void fun1() {
			us.save();
		}
	}

使用注解配置aop(了解):

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">
<!-- 准备工作:导入aop约束命名空间 -->
<!-- 1.配置目标对象 -->
	<bean name="userService" class="com.rabbit.interf.UserServiceImp"></bean>
<!-- 2.配置通知类 -->
	<bean name="myAdvice" class="com.rabbit.annotation_aop.MyAdvice"></bean>
<!-- 3.开启使用注解完成织入 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

注解配置:

//通知类
@Aspect
//这个注解表示该类为一个通知类
public class MyAdvice {
	
	//前置通知
	@Before("execution(* com.rabbit.interf.*ServiceImp.*(..))")
	public void before() {
		System.out.println("前置通知");
	}
	
	//后置通知:如果方法出现异常不调用
	@AfterReturning("execution(* com.rabbit.interf.*ServiceImp.*(..))")
	public void afterreturning() {
		System.out.println("后置通知,异常不调用");
	}
	//环饶通知
	@Around("execution(* com.rabbit.interf.*ServiceImp.*(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("环绕通知之前的部分");
		Object proceed = pjp.proceed();//调用目标方法
		System.out.println("环绕通知之后的部分");
		return proceed;
	}
	//异常通知
	@AfterThrowing("execution(* com.rabbit.interf.*ServiceImp.*(..))")
	public void afterException() {
		System.out.println("出事了之后执行的异常通知");
	}
	//后置通知
	@After("execution(* com.rabbit.interf.*ServiceImp.*(..))")
	public void after() {
		System.out.println("出现异常也会调用");
	}
}

spring整合JDBC

  • spring中提供了一个可以操作数据库的对象,对象封装了jdbc技术:JDBCTemplate 模板对象;与DButils中的QueryRunner非常相似;

  • 导包:4+2;spring test;spring aop c3p0连接池;jdbc驱动;spring-jdbc;spring-tx;

测试:

准备增删改查的类:

package com.rabbit.jdbctemplate;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
//使用jdbc模板实现增删改查
public class UserDaoImp implements UserDao {
	private JdbcTemplate jt;
	public JdbcTemplate getJt() {
		return jt;
	}

	public void setJt(JdbcTemplate jt) {
		this.jt = jt;
	}

	@Override
	public void save(User u) {
		String sql = "insert into t_user values(?,?)";
		jt.update(sql,u.getId(), u.getName());
	}

	@Override
	public void delete(Integer id) {
		String sql = "delete from t_user where id = ?";
		jt.update(sql, id);
	}

	@Override
	public void update(User u) {
		String sql = "update t_user set name = ? where id = ?";
		jt.update(sql,u.getName(),u.getId());
	}

	@Override
	public User getById(Integer id) {
		String sql = "select * from t_user where id = ?";
		User user =  jt.queryForObject(sql, new RowMapper<User>() {

			@Override
			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setName(rs.getString("name"));
				return u;
			}},id);
		return user;
	}

	@Override
	public int getTotalCount() {
		String sql = "select count(*) from t_user";
		Integer count = jt.queryForObject(sql, Integer.class);
		return count;
	}

	@Override
	public List<User> getAll() {
		String sql = "select * from t_user";
		List<User> list = jt.query(sql, new RowMapper<User>() {

			@Override
			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				User u = new User();
				u.setId(rs.getInt("id"));
				u.setName(rs.getString("name"));
				return u;
			}});
		return list;
	}

}

spring容器配置文件配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd ">

	<!-- 1.将连接池放入spring容器 -->
	<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mysqltest?serverTimezone=GMT%2B8"></property>
		<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
		<property name="user" value="root"></property>
		<property name="password" value="admin"></property>
	</bean>
	<!-- 2.将jdbctemplate放入spring容器 -->
	<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 3.将UserDao放入Spring容器 -->
	<bean name="userDao" class="com.rabbit.jdbctemplate.UserDaoImp">
		<property name="jt" ref="jdbcTemplate"></property>
	</bean>
</beans>

代码测试:增删改查

package com.rabbit.jdbctemplate;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.mchange.v2.c3p0.ComboPooledDataSource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
	@Resource(name="userDao")
	private UserDao ud;
	@Test
	public void fun1() throws Exception {
		
		//准备连接池
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
		dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mysqltest?serverTimezone=GMT%2B8");
		dataSource.setUser("root");
		dataSource.setPassword("admin");
		//创建JDBC模板对象
		JdbcTemplate jt = new JdbcTemplate();
		jt.setDataSource(dataSource);

		//书写sql
		String sql = "insert into t_user values(null,'rose')";
		//执行
		jt.update(sql);
	}
	@Test
	public void fun2() throws Exception {
		User u = new User();
		u.setId(2);
		u.setName("杨丽");
		ud.save(u);
	}
	@Test
	public void fun3() throws Exception {
		User i = ud.getById(2);
		System.out.println(i.toString());
	}
	@Test
	public void fun4() throws Exception {
		ud.delete(2);
	}
}

使用properties配置文件封装连接池,用spring取读取配置文件获得连接数据库的数据;

properties配置文件:

	jdbc.jdbcUrl=jdbc:mysql://localhost:3306/mysqltest?serverTimezone=GMT%2B8
	jdbc.driverClass=com.mysql.cj.jdbc.Driver
	jdbc.user=root
	jdbc.password=admin

修改spring配置文件:

	<!-- 指定spring读取db.properties配置 -->
	<context:property-placeholder  location="classpath:db.properties" />
	<!-- 1.将连接池放入spring容器 -->
	<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>

Spring中的aop事务

  • 事务

    • 事务特性:acid
    • 事务并发问题:脏读,幻读;不可重复读
    • 事务的隔离级别:
      • 1:读未提交
      • 2:读已提交
      • 4:可重复度
      • 8:串行化
  • spring封装了事务管理代码:

    • 事务操作
      • 打开事务
      • 提交事务
      • 回滚事务
    • 事务操作对象
      • 因为在不同平台操作事务代码各不相同,spring提供了一个接口(PlatformTransactionManager)
      • PlatformTransactionManager接口有各平台的实现类:
        • DataSourceTransactionManager:jdbc事务管理
        • HibernateTransactionManager:Hibernate事务管理
      • Spring管理事务的属性介绍:
        • 事务的隔离级别:1.2.4.8
        • 是否只读:false、true
        • 事务的传播行为:有7个供我们选择:基本只会用这个:PROPACATION_REQUIRED(默认):支持当前事务,如果不存在,就新建一个

spring管理事务方式:

  1. 编码式(了解):代码里管理事务,缺点,需要修改的时候得去修改原码

  2. 将核心事务管理器放到spring容器

  3. xml配置(常用,开发中用这个):

  4. 导包

  5. 导入命名空间约束:xsi,beans:最基本,aop:配置aop,tx:配置事务,context:注解,读取properties配置文件

  6. 配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    	<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
    <!-- 指定spring读取db.properties配置 -->
    <context:property-placeholder location="classpath:db.properties"  />
    
    <!-- 事务核心管理器,封装了所有事务操作. 依赖于连接池 -->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
    	<property name="dataSource" ref="dataSource" ></property>
    </bean>
    <!-- 事务模板对象 -->
    <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" >
    	<property name="transactionManager" ref="transactionManager" ></property>
    </bean>
    
    <!-- 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager" >
    	<tx:attributes>
    		<!-- 以方法为单位,指定方法应用什么事务属性
    			isolation:隔离级别
    			propagation:传播行为
    			read-only:是否只读
    		 -->
    		<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    		<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    		<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    		<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    		<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    		<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    		<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
    		<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
    		<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    	</tx:attributes>
    </tx:advice>
    

    <!-- 配置织入 -->
    <aop:config  >
    	<!-- 配置切点表达式 -->
    	<aop:pointcut expression="execution(* com.rabbit.service.*ServiceImpl.*(..))" id="txPc"/>
    	<!-- 配置切面 : 通知+切点
    		 	advice-ref:通知的名称
    		 	pointcut-ref:切点的名称
    	 -->
    	<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
    </aop:config>
    

    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    		<property name="driverClass" value="${jdbc.driverClass}"></property>
    		<property name="user" value="${jdbc.user}"></property>
    		<property name="password" value="${jdbc.password}"></property>
    	</bean>
    


    <!-- 2.Dao-->
    <bean name="accountDao" class="com.rabbit.dao.AccountDaoImpl" >
    	<property name="dataSource" ref="dataSource" ></property>
    </bean>
    <!-- 3.Service-->
    <bean name="accountService" class="com.rabbit.service.AccountServiceImpl" >
    	<property name="ad" ref="accountDao" ></property>
    	<property name="tt" ref="transactionTemplate" ></property>
    </bean>  
    
    </beans>
    
  7. 注解配置(常用,开发中用这个):

  8. 导包

  9. 导入命名空间约束:xsi,beans:最基本,aop:配置aop,tx:配置事务,context:注解,读取properties配置文件

  10. 配置文件:

    tx:annotation-driven/
    添加注解到测试的方法或者类上(类上可以管理所有的方法,但是优先级不如加在方法上面):

    @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
    	public void transfer(Integer from, Integer to, Double money) {
    		//减钱
    		ad.dereaseMoney(from, money);
    		//int i = 1/0;
    		//价钱
    		ad.increaseMoney(to, money);
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值