目录
- 1 Spring 入门
- 2 IOC与ID的概念:
- 3 BeanFactory与applicationContext
- 4 配置详解:
- 5 使用注解代替XML配置
- 6 安装STS插件
- 7 spring整合junit测试
- 8 AOP思想介绍
- 9 AOP实现原理
- 10 AOP术语介绍
- 11 AOP
- 12 spring的aop注解配置
- 13 spring整合jdbc-jdbc模板对象
- 14 jdbc模板api详解
- 15 jdbc扩展-JDBCDaoSupport
- 16 读取db.properties配置
- 17 Spring事务管理
- 18 Spring事务入门
- 19 三大框架整合理论
- 20 导包
- 21 单独整合(配置)spring容器
- 22 单独整合(配置)Struts2
- 23 整合struts2与spring
- 24 单独配置Hibernate
- 25 整合hibernate与spring
- 26 spring整合C3P0连接池
- 27 HibernateTemplate模板操作数据库
- 28 整合AOP事务
- 29 扩大session作用范围
- Spring 入门
- IOC与ID的概念:
- BeanFactory与applicationContext
- 配置详解:
- 使用注解代替XML配置
- 安装STS插件
- spring整合junit测试
- AOP思想介绍
- AOP实现原理
- AOP术语介绍
- AOP
- spring的aop注解配置
- spring整合jdbc-jdbc模板对象
- jdbc模板api详解
- jdbc扩展-JDBCDaoSupport
- 读取db.properties配置
- Spring事务管理
- Spring事务入门
- 三大框架整合理论
- 导包
- 单独整合(配置)spring容器
- 单独整合(配置)Struts2
- 整合struts2与spring
- 单独配置Hibernate
- 整合hibernate与spring
- spring整合C3P0连接池
- HibernateTemplate模板操作数据库
- 整合AOP事务
- 扩大session作用范围
Spring 入门
1. 导包
2. 创建user对象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public class User { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } } |
3.创建配置文件
配置文件放哪、叫什么名字都随意,但是建议在src下建立名为applicationContext.xml作为spring的配置文件。
4.导入约束(操作复杂)
5.书写配置注册对象到容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?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元素:使用该元素描述需要spring容器管理的对象 class属性:被管理对象的完整类名. name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象. 可以重复.可以使用特殊字符. id属性: 与name属性一模一样. 名称不可重复.不能使用特殊字符. 结论: 尽量使用name属性. --> <bean name="user" class="com.benz.bean.User"></bean> <!-- 导入其他spring配置文件 --> <import resource="com/benz/create/applicationContext.xml" /> </beans> |
6.测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Demo { @Test public void fun1(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user"); //3 打印user对象 System.out.println(u); } } |
IOC与ID的概念:
BeanFactory与applicationContext
BeanFactory(过时)
Spring原始接口,针对原始接口的实现类,功能较为单一。
BeanFactory接口实现类的容器。特点是每次在获得对象时才会创建对象
aplicationContext
每次容器启动的时候会创建容器中配置的所有对象。并提供更多功能。
从类路径下加载配置文件:ClassPathXmlApplicationContext(重点)
从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext
结论:开发中,使用applicationContext。在资源匮乏的环境可以使用BeanFactory。
配置详解:
Bean元素:
1 2 3 4 5 6 7 8 9 10 |
<!-- 将User对象交给spring容器管理 --> <!-- Bean元素:使用该元素描述需要spring容器管理的对象 class属性:被管理对象的完整类名. name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象. 可以重复.可以使用特殊字符. id属性: 与name属性一模一样. 名称不可重复.不能使用特殊字符. 结论: 尽量使用name属性. --> <bean name="user" class="com.benz.bean.User"></bean> |
三种对象创建方式:
1.空参构造(重点)
User类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class User { public User() { System.out.println("User对象空参构造方法!!!!"); } private String name; private Integer age; private Car car; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } |
测试方法:
1 2 3 4 5 6 7 8 9 10 11 |
@Test //创建方式1:空参构造 public void fun1(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/b_create/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user"); //3 打印user对象 System.out.println(u); } |
配置:
1 2 3 |
!-- 创建方式1:空参构造创建 --> <bean name="user" class="cn.itcast.bean.User" init-method="init" destroy-method="destory" ></bean> |
2.静态工厂(了解)
静态类:
1 2 3 4 5 6 7 |
public static User createUser(){ System.out.println("静态工厂创建User"); return new User(); } |
测试类:
1 2 3 4 5 6 7 8 9 10 |
//创建方式2:静态工厂 @Test public void fun2(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/b_create/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user2"); //3 打印user对象 System.out.println(u); } |
配置:
1 2 3 4 5 6 |
<!-- 创建方式2:静态工厂创建 调用UserFactory的createUser方法创建名为user2的对象.放入容器 --> <bean name="user2" class="cn.itcast.b_create.UserFactory" factory-method="createUser" ></bean> |
3.实例工厂(了解)
实例类:
1 2 3 4 5 6 7 |
public User createUser2(){ System.out.println("实例工厂创建User"); return new User(); } |
测试类:
1 2 3 4 5 6 7 8 9 10 |
//创建方式3:实例工厂 @Test public void fun3(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/b_create/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user3"); //3 打印user对象 System.out.println(u); } |
配置:
1 2 3 4 5 6 7 8 9 |
<!-- 创建方式3:实例工厂创建 调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器 --> <bean name="user3" factory-bean="userFactory" factory-method="createUser2" ></bean> <bean name="userFactory" class="cn.itcast.b_create.UserFactory" ></bean> |
scope属性:
singleton(默认值):单例对象。被标识为单例的对象在spring容器中只会存在一个实例。
配置
1 |
<bean name="user" class="com.benz.bean.User" scope=”singleton”></bean> |
prototype:多例原型。被标识为多例的对象,每次再获得才会创建,每次创建都是新的对象。整合Struts2时,ActionBean必须配置为多例。
配置
1 |
<bean name="user" class="com.benz.bean.User" scope=” prototype”></bean> |
request(了解):web环境下。对象与request生命周期一致。
session(了解):web环境下。对象与session生命周期一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Test //scope:singleton 单例 //scope:prototype 多例 public void fun4(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/b_create/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user"); User u2 = (User) ac.getBean("user"); User u3 = (User) ac.getBean("user"); User u4 = (User) ac.getBean("user"); System.out.println(u2==u4);//单例:true //多例:false //3 打印user对象 System.out.println(u); } |
生命周期属性:
配置一个方法作为生命周期初始化方法。Spring会在对象创建之后立即调用。
Init-method
配置一个方法作为生命周期销毁方法。Spring容器在关闭并销毁所有容器中的对象之前调用。
Destory-method
User类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
public class User { public User() { System.out.println("User对象空参构造方法!!!!"); } private String name; private Integer age; private Car car; public User(String name, Car car) { System.out.println("User(String name, Car car)!!"); this.name = name; this.car = car; } public User(Car car,String name) { System.out.println("User(Car car,String name)!!"); this.name = name; this.car = car; } public User(Integer name, Car car) { System.out.println("User(Integer name, Car car)!!"); this.name = name+""; this.car = car; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public void init(){ System.out.println("我是初始化方法!"); } public void destory(){ System.out.println("我是销毁方法!"); } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", car=" + car + "]"; } } |
配置
1 2 |
<bean name="user" class="com.benz.bean.User" init-method="init" destroy-method="destory" ></bean> |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 |
@Test //测试生命周期方法 public void fun5(){ //1 创建容器对象 ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/b_create/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user"); //3 打印user对象 System.out.println(u); //关闭容器,触发销毁方法 ac.close(); } |
模块化配置:
1 2 |
<!-- 导入其他spring配置文件 --> <import resource="com/benz/create/applicationContext.xml" /> |
属性注入
User类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
public class User { public User() { System.out.println("User对象空参构造方法!!!!"); } private String name; private Integer age; private Car car; public User(String name, Car car) { System.out.println("User(String name, Car car)!!"); this.name = name; this.car = car; } public User(Car car,String name) { System.out.println("User(Car car,String name)!!"); this.name = name; this.car = car; } public User(Integer name, Car car) { System.out.println("User(Integer name, Car car)!!"); this.name = name+""; this.car = car; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public void init(){ System.out.println("我是初始化方法!"); } public void destory(){ System.out.println("我是销毁方法!"); } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", car=" + car + "]"; } } |
Car类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class Car { private String name; private String color; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } @Override public String toString() { return "Car [name=" + name + ", color=" + color + "]"; } } |
Set方式(重点):
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!-- set方式注入: --> <bean name="user" class="cn.itcast.bean.User" > <!--值类型注入: 为User对象中名为name的属性注入tom作为值 --> <property name="name" value="tom" ></property> <property name="age" value="18" ></property> <!-- 引用类型注入: 为car属性注入下方配置的car对象 --> <property name="car" ref="car" ></property> </bean> <!-- 将car对象配置到容器中 --> <bean name="car" class="cn.itcast.bean.Car" > <property name="name" value="兰博基尼" ></property> <property name="color" value="黄色" ></property> </bean> |
测试:
1 2 3 4 5 6 7 8 9 10 11 |
@Test public void fun1(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/c_injection/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user"); //3 打印user对象 System.out.println(u); } |
构造函数方式(重点):
配置
1 2 3 4 5 6 7 8 |
<!-- 构造函数注入 --> <bean name="user2" class="cn.itcast.bean.User" > <!-- name属性: 构造函数的参数名 --> <!-- index属性: 构造函数的参数索引 --> <!-- type属性: 构造函数的参数类型--> <constructor-arg name="name" index="0" type="java.lang.Integer" value="999" ></constructor-arg> <constructor-arg name="car" ref="car" index="1" ></constructor-arg> </bean> |
测试
1 2 3 4 5 6 7 8 9 10 11 |
@Test public void fun2(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/c_injection/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user2"); //3 打印user对象 System.out.println(u); } |
P名称空间(了解):
配置
1 2 3 4 5 6 7 8 |
<!-- p名称空间注入, 走set方法 1.导入P名称空间 xmlns:p="http://www.springframework.org/schema/p" 2.使用p:属性完成注入 |-值类型: p:属性名="值" |-对象类型: p:属性名-ref="bean名称" --> <bean name="user3" class="cn.itcast.bean.User" p:name="jack" p:age="20" p:car-ref="car" > </bean> |
测试:
1 2 3 4 5 6 7 8 9 10 11 |
@Test public void fun3(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/c_injection/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user3"); //3 打印user对象 System.out.println(u); } |
SPEL表达式(了解)
配置:
1 2 3 4 5 6 7 8 |
<!-- spel注入: spring Expression Language sping表达式语言 --> <bean name="user4" class="cn.itcast.bean.User" > <property name="name" value="#{user.name}" ></property> <property name="age" value="#{user3.age}" ></property> <property name="car" ref="car" ></property> </bean> |
测试:
1 2 3 4 5 6 7 8 9 10 11 |
@Test public void fun4(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/c_injection/applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user4"); //3 打印user对象 System.out.println(u); } |
复杂类型注入
创建类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class CollectionBean { private Object[] arr;//数组类型注入 private List list;//list/set 类型注入 private Map map;//map类型注入 private Properties prop;//properties类型注入 public Object[] getArr() { return arr; } public void setArr(Object[] arr) { this.arr = arr; } public List getList() { return list; } public void setList(List list) { this.list = list; } public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } public Properties getProp() { return prop; } public void setProp(Properties prop) { this.prop = prop; } @Override public String toString() { return "CollectionBean [arr=" + Arrays.toString(arr) + ", list=" + list + ", map=" + map + ", prop=" + prop + "]"; } } |
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<!-- 复杂类型注入 --> <bean name="cb" class="cn.itcast.c_injection.CollectionBean" > <!-- 如果数组中只准备注入一个值(对象),直接使用value|ref即可 <property name="arr" value="tom" ></property> --> <!-- array注入,多个元素注入 --> <property name="arr"> <array> <value>tom</value> <value>jerry</value> <ref bean="user4" /> </array> </property> <!-- 如果List中只准备注入一个值(对象),直接使用value|ref即可 <property name="list" value="jack" ></property>--> <property name="list" > <list> <value>jack</value> <value>rose</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> <entry key-ref="user3" value-ref="user2" ></entry> </map> </property> <!-- prperties 类型注入 --> <property name="prop" > <props> <prop key="driverClass">com.jdbc.mysql.Driver</prop> <prop key="userName">root</prop> <prop key="password">1234</prop> </props> </property> </bean> |
测试:
1 2 3 4 5 6 7 8 9 10 11 |
@Test public void fun5(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/c_injection/applicationContext.xml"); //2 向容器"要"user对象 CollectionBean cb = (CollectionBean) ac.getBean("cb"); //3 打印user对象 System.out.println(cb); } |
使用注解代替XML配置
导入包(aop包):spring-aop-4.2.4.RELEASE.jar
1.为主配置文件引入新的命名空间(约束)(context约束)
2.开启使用注解代理配置文件
1 2 3 4 |
<!-- 指定扫描com.benz.bean包下的所有类中的注解. 注意:扫描包时.会扫描指定报下的所有子孙包 --> <context:component-scan base-package="com.benz.bean"></context:component-scan> |
3.使用注解
4.测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Demo { @Test public void fun1(){ //1 创建容器对象 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //2 向容器"要"user对象 User u = (User) ac.getBean("user"); //3 打印user对象 System.out.println(u); } } |
5.其他注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
//<bean name="user" class="cn.itcast.bean.User" /> //@Component("user")//开始就只有这一个,为解决知道调用那个层的对象, //有了以下三个注解,其实和Component是一样的 // // @Service("user") // service层 // @Controller("user") // web层 @Repository("user")// dao层 //指定对象的作用范围 singleton:单例 prototype:多例 @Scope(scopeName="singleton") public class User { private String name; @Value("18")//(赋值方式一)通过反射field赋值(不推荐,破坏封装性) private Integer age; //类注入有以下三种,使用前注册car类 /* @Component("car") public class Car { }*/ //@Autowired //自动装配 //问题:如果匹配多个类型一致的对象.将无法选择具体注入哪一个对象. //@Qualifier("car2")//使用@Qualifier注解告诉spring容器自动装配哪个名称的对象 @Resource(name="car")//手动注入,指定注入哪个名称的对象 private Car car; public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public String getName() { return name; } @Value("tom") //(赋值方式二)通过set方法赋值 public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @PostConstruct //在对象被创建后调用.init-method public void init(){ System.out.println("我是初始化方法!"); } @PreDestroy //在销毁之前调用.destory-method public void destory(){ System.out.println("我是销毁方法!"); } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", car=" + car + "]"; } } |
安装STS插件
spring整合junit测试
1.导包
4基础包+2日记包+aop包+test包
test包:spring-test-4.2.4.RELEASE.jar
2.注解的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//帮我们创建容器 @RunWith(SpringJUnit4ClassRunner.class) //指定创建容器时使用哪个配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class Demo { //将名为user的对象注入到u变量中 @Resource(name="user") private User u; @Test public void fun1(){ System.out.println(u); } @Test public void fun2(){ System.out.println(u); } @Test public void fun3(){ System.out.println(u); } } |
AOP思想介绍
AOP实现原理
AOP实现原理是由动态代理与CGLib代理共同完成,两种代理都使用,如果有接口,优先使用动态代理,没有就使用CGLib代理,目的是可以代理所有类。
动态代理
被代理对象必须实现接口,才能产生代理对象。如果没有接口,将不能使用动态代理技术。
CGLib代理
第三方代理技术,CGLib代理可以对任何类生成代理。代理的原理是对目标对象进行继承代理。如果目标对象被final修饰,那么该类无法被CGLib代理。(Hibernate也使用CGLib代理,也就为什么有一项规定,方法不能被final修饰)
AOP术语介绍
- Joinpoint(连接点):目标对象中,所有可以增强的方法。
- Pointcut(切入点):目标对象,已经增强的方法。
- Advice(通知/增强):增强的代码。
- Target(目标对象):被代理对象。
- Weaving(织入):将通知应用到切入点的过程。
- Proxy(代理):将通知织入到目标对象之后,形成代理对象。
- Aspect(切面):是切入点和通知的结合。
AOP
1.导包
4基础包+2日志包+spring-aop-4.2.4.RELEASE.jar+spring-aspects-4.2.4.RELEASE.jar+com.springsource.org.aopalliance-1.0.0.jar+com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar路径:spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
2.准备目标对象
userservice接口:
1 2 3 4 5 6 7 |
public interface UserService { public void add(); public void delete(); public void update(); public void find(); } |
目标对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("添加用户!!!"); } @Override public void delete() { System.out.println("删除用户!!!"); } @Override public void update() { System.out.println("更新用户!!!"); } @Override public void find() { System.out.println("查询用户!!!"); } } |
3.准备通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
//通知类 public class MyAdvice { //前置通知 // |-目标方法运行之前调用 //后置通知(如果出现异常不会调用) // |-在目标方法运行之后调用 //环绕通知 // |-在目标方法之前和之后都调用 //异常拦截通知 // |-如果出现异常,就会调用 //后置通知(无论是否出现 异常都会调用) // |-在目标方法运行之后调用 //---------------------------------------------------------------- //前置通知 public void before(){ System.out.println("这是前置通知!!"); } //后置通知 public void afterReturning(){ 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 after(){ System.out.println("这是后置通知(出现异常也会调用)!!"); } } |
4.配置进行织入,将通知织入目标对象中
配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<!-- 准备工作: 导入aop(约束)命名空间 --> <!-- 1.配置目标对象 --> <bean name="userService" class="com.benz.serviceImpl.UserServiceImpl" ></bean> <!-- 2.配置通知对象 --> <bean name="myAdvice" class="com.benz.aspect.MyAdvice" ></bean> <!-- 3.配置将通知织入目标对象 --> <aop:config> <!-- 配置切入点 public void com.benz.serviceImpl.UserServiceImpl.add() void com.benz.serviceImpl.UserServiceImpl.add() * com.benz.serviceImpl.UserServiceImpl.add() * com.benz.serviceImpl.UserServiceImpl.*() * com.benz.serviceImpl.*ServiceImpl.*(..) * com.benz.service..*ServiceImpl.*(..) --> <aop:pointcut expression="execution(* com.benz.serviceImpl.*ServiceImpl.*(..))" 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> |
5.测试代码
1 2 3 4 5 6 7 8 9 10 11 12 |
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class AopTest { @Resource(name="userService") private UserService us; @Test public void fun1(){ us.add(); } } |
spring的aop注解配置
1.配置applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 |
<?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.benz.serviceImpl.UserServiceImpl" ></bean> <!-- 2.配置通知对象 --> <bean name="myAdvice" class="com.benz.aspect.MyAdvice" ></bean> <!-- 3.开启使用注解完成织入 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans> |
2.注解通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
//通知类 @Aspect //表示该类是一个通知类 public class MyAdvice { //复用execution(* com.benz.serviceImpl.*ServiceImpl.*(..)) //MyAdvice.pc()相当于execution(* com.benz.serviceImpl.*ServiceImpl.*(..)) @Pointcut("execution(* com.benz.serviceImpl.*ServiceImpl.*(..))") public void pc(){} //前置通知 //指定该方法是前置通知,并制定切入点 @Before("MyAdvice.pc()") public void before(){ System.out.println("这是前置通知!!"); } //后置通知 @AfterReturning("MyAdvice.pc()") public void afterReturning(){ System.out.println("这是后置通知(如果出现异常不会调用)!!"); } //环绕通知 @Around("MyAdvice.pc()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("这是环绕通知之前的部分!!"); Object proceed = pjp.proceed();//调用目标方法 System.out.println("这是环绕通知之后的部分!!"); return proceed; } //异常通知 @AfterThrowing("MyAdvice.pc()") public void afterException(){ System.out.println("出事啦!出现异常了!!"); } //后置通知 @After("MyAdvice.pc()") public void after(){ System.out.println("这是后置通知(出现异常也会调用)!!"); } } |
3.测试类
1 2 3 4 5 6 7 8 9 10 11 12 |
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class AopTest { @Resource(name="userService") private UserService us; @Test public void fun1(){ us.add(); } } |
spring整合jdbc-jdbc模板对象
JDBCTemplate(JDBC模板对象):Spring中提供了一个可以操作数据库的对象。对象封装了JDBC技术。与DBUtils中的QueryRunner非常相似。
1.导包
4基础包+2日志包+aop包+test包+C3P0连接池+JDBC驱动+spring-jdbc+spring-tx
2.准备数据库sshdemo,创建表jt_user
1 2 3 4 5 |
CREATE TABLE `jt_user` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` char(32) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
3.测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Test public void fun1() throws Exception { //1.准备连接池 //平常连接池是引入配置文件,也可以用set方法配置 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //配置连接池 dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql:///sshdemo"); dataSource.setUser("root"); dataSource.setPassword("root"); //2.创建JdbcTemplate JdbcTemplate jt = new JdbcTemplate(dataSource); String sql="insert into jt_user values(null,'钟国仁')"; //3.执行操作 jt.update(sql); } |
jdbc模板api详解
创建接口:UserDao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public interface UserDao { //增 void save(User u); //删 void delete(Integer id); //改 void update(User u); //查 User getById(Integer id); //查 int getTotalCount(); //查 List<User> getAll(); } |
使用JDBC模板实现增删改查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
//使用JDBC模板实现增删改查 public class UserDaoImpl implements UserDao { private JdbcTemplate jt; public void setJt(JdbcTemplate jt) { this.jt = jt; } @Override public void save(User u) { String sql = "insert into jt_user values(null,?) "; jt.update(sql, u.getName()); } @Override public void delete(Integer id) { String sql = "delete from jt_user where id = ? "; jt.update(sql,id); } @Override public void update(User u) { String sql = "update jt_user set name = ? where id=? "; jt.update(sql, u.getName(),u.getId()); } @Override public User getById(Integer id) { String sql = "select * from jt_user where id = ? "; return 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); } @Override public int getTotalCount() { String sql = "select count(*) from jt_user "; Integer count = jt.queryForObject(sql, Integer.class); return count; } @Override public List<User> getAll() { String sql = "select * from jt_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; } } |
连接池&JDBC模板&Dao配置到spring容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!-- 1.将连接池放入spring容器 --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="jdbcUrl" value="jdbc:mysql:///sshdemo" ></property> <property name="driverClass" value="com.mysql.jdbc.Driver" ></property> <property name="user" value="root" ></property> <property name="password" value="root" ></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.benz.jdbcTemplate.UserDaoImpl" > <property name="jt" ref="jdbcTemplate" ></property> </bean> |
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class Demo { @Resource(name="userDao") private UserDao ud; @Test public void fun2() throws Exception{ User u = new User(); u.setName("tom"); ud.save(u); } @Test public void fun3() throws Exception{ User u = new User(); u.setId(2); u.setName("jack"); ud.update(u); } @Test public void fun4() throws Exception{ ud.delete(2); } @Test public void fun5() throws Exception{ System.out.println(ud.getTotalCount()); } @Test public void fun6() throws Exception{ System.out.println(ud.getById(1)); } @Test public void fun7() throws Exception{ System.out.println(ud.getAll()); } } |
jdbc扩展-JDBCDaoSupport
UserDaoImpl类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
//使用JDBC模板实现增删改查 public class UserDaoImpl extends JdbcDaoSupport implements UserDao { /* * JdbcTemplate对象由JdbcDaoSupport自动生成 * 所以 * JdbcTemplate jt 改由 super.getJdbcTemplate() 获取 */ @Override public void save(User u) { String sql = "insert into jt_user values(null,?) "; super.getJdbcTemplate().update(sql, u.getName()); } @Override public void delete(Integer id) { String sql = "delete from jt_user where id = ? "; super.getJdbcTemplate().update(sql,id); } @Override public void update(User u) { String sql = "update jt_user set name = ? where id=? "; super.getJdbcTemplate().update(sql, u.getName(),u.getId()); } @Override public User getById(Integer id) { String sql = "select * from jt_user where id = ? "; return super.getJdbcTemplate().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); } @Override public int getTotalCount() { String sql = "select count(*) from jt_user "; Integer count = super.getJdbcTemplate().queryForObject(sql, Integer.class); return count; } @Override public List<User> getAll() { String sql = "select * from jt_user "; List<User> list = super.getJdbcTemplate().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; } } |
配置修改
1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- 1.将连接池放入spring容器 --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="jdbcUrl" value="jdbc:mysql:///sshdemo" ></property> <property name="driverClass" value="com.mysql.jdbc.Driver" ></property> <property name="user" value="root" ></property> <property name="password" value="root" ></property> </bean> <!-- 2.将UserDao放入spring容器 --> <bean name="userDao" class="com.benz.jdbcTemplate.UserDaoImpl" > <property name="dataSource" ref="dataSource" ></property> </bean> |
读取db.properties配置
目的:将数据库连接信息抽取出来,单独为db.properties文件。
src下,创建db.properties
1 2 3 4 |
jdbc.jdbcUrl=jdbc\:mysql\:///sshdemo jdbc.driverClass=com.mysql.jdbc.Driver jdbc.user=root jdbc.password=root |
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!-- 指定spring读取db.properties配置 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 1.将连接池放入spring容器 --> <!-- 使用 ${}获取db.properties的值--> <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.将UserDao放入spring容器 --> <bean name="userDao" class="com.benz.jdbcTemplate.UserDaoImpl" > <property name="dataSource" ref="dataSource" ></property> </bean> |
Spring事务管理
Spring封装了事务管理代码
JDBC、Hibernate、MyBatis都有自己实现事务的方法,在不同平台,操作事务的代码各不相同。Spring提供了一个接口:PlatformTransactionManager接口。
Spring通过这个接口,对各个平台的事务进行了封装,如:JDBCTransactionManager、HibernateTransactionManager等。
在Spring中使用事务管理,最为核心的对象就是TransactionManager对象。(要使用事务TransactionManager必须要配置)
Spring管理事务的属性介绍
事务隔离级别
- 1:读未提交
- 2:读已提交
- 4:可重复读
- 8:串行化
是否只读
- true :只读(不能操作数据库,只能查,增、删、改会报错)
- false:可操作数据库
事务传播行为
保证同一个事务中
- PROPAGATION_REQUIRED 支持当前事务,如果不存在就新建一个(默认)
- PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
- PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常
保证没有在同一个事务中
- PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
- PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
- PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
- PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
Spring事务入门
事务环境准备
以转账为例:
创建转账表sp_account
1 2 3 4 5 6 |
CREATE TABLE `sp_account` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` char(32) NOT NULL DEFAULT '', `money` double(10,0) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 |
DAO层:
接口:AccountDao
1 2 3 4 5 6 7 |
public interface AccountDao { //加钱 void increaseMoney(Integer id,Double money); //减钱 void decreaseMoney(Integer id,Double money); } |
实现接口:AccountDaoImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { @Override public void increaseMoney(Integer id, Double money) { getJdbcTemplate().update("update t_account set money = money+? where id = ? ", money,id); } @Override public void decreaseMoney(Integer id, Double money) { getJdbcTemplate().update("update t_account set money = money-? where id = ? ", money,id); } } |
service层:
接口:AccountService
1 2 3 4 5 6 |
public interface AccountService { //转账方法 void transfer(Integer from,Integer to,Double money); } |
实现接口: AccountServiceImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class AccountServiceImpl implements AccountService{ private AccountDao ad; @Override public void transfer(Integer from, Integer to, Double money) { //加钱 ad.add(to, money); //手动制造错误 //int i=1/0; //减钱 ad.reduce(from, money); } public void setAd(AccountDao ad) { this.ad = ad; } } |
配置:
dataSource注入AccountDao,AccountDao注入AccountService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!-- 1.将连接池放入spring容器 --> <!-- 使用 ${}获取db.properties的值--> <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.benz.dao.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 3. Service --> <bean name="accountService" class="com.benz.serviceImpl.AccountServiceImpl" > <property name="ad" ref="accountDao" ></property> </bean> |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class TestAccount { @Resource(name="accountService") private AccountService as; @Test public void fun1(){ as.transfer(1, 2, 100d); } } |
spring事务使用方式一:Transaction模板(了解)
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<!-- 指定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> <!-- 1.将连接池放入spring容器 --> <!-- 使用 ${}获取db.properties的值--> <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.将UserDao放入spring容器 --> <bean name="userDao" class="com.benz.jdbcTemplate.UserDaoImpl" > <property name="dataSource" ref="dataSource" ></property> </bean> <bean name="accountDao" class="com.benz.dao.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <bean name="accountService" class="com.benz.serviceImpl.AccountServiceImpl" > <property name="ad" ref="accountDao" ></property> <property name="tt" ref="transactionTemplate" ></property> </bean> </beans> |
service层使用事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public class AccountServiceImpl implements AccountService{ private AccountDao ad; //事务管理模板对象 private TransactionTemplate tt; public void setTt(TransactionTemplate tt) { this.tt = tt; } public void setAd(AccountDao ad) { this.ad = ad; } @Override public void transfer(final Integer from, final Integer to, final Double money) { //让事务管理模板执行事务 tt.execute(new TransactionCallbackWithoutResult() { //doInTransactionWithoutResult里放的是要执行的事务 @Override protected void doInTransactionWithoutResult(TransactionStatus arg0) { //加钱 ad.add(to, money); //手动报错 //int i=1/0; //减钱 ad.reduce(from, money); } }); } } |
测试代码:不变
spring事务使用方式二:xml配置aop事务(重点)
- aop包
- aspect包
- aop联盟包
- weaving织入包
配置通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<!-- 指定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.benz.service.*ServiceImpl.*(..))" id="txPc"/> <!-- 配置切面 : 通知+切点 advice-ref:通知的名称 pointcut-ref:切点的名称 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" /> </aop:config> <!-- 1.将连接池放入spring容器 --> <!-- 使用 ${}获取db.properties的值--> <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.将UserDao放入spring容器 --> <bean name="userDao" class="com.benz.jdbcTemplate.UserDaoImpl" > <property name="dataSource" ref="dataSource" ></property> </bean> <bean name="accountDao" class="com.benz.dao.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <bean name="accountService" class="com.benz.serviceImpl.AccountServiceImpl" > <property name="ad" ref="accountDao" ></property> <property name="tt" ref="transactionTemplate" ></property> </bean> |
其他不变。
spring事务使用方式二:注解配置aop事务(重点)
导包、引入新约束和XML配置AOP事务一样
开启注解管理事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<!-- 指定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> <!-- 开启注解管理aop事务 --> <tx:annotation-driven/> <!-- 1.将连接池放入spring容器 --> <!-- 使用 ${}获取db.properties的值--> <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.将UserDao放入spring容器 --> <bean name="userDao" class="com.benz.jdbcTemplate.UserDaoImpl" > <property name="dataSource" ref="dataSource" ></property> </bean> <bean name="accountDao" class="com.benz.dao.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <bean name="accountService" class="com.benz.serviceImpl.AccountServiceImpl" > <property name="ad" ref="accountDao" ></property> <property name="tt" ref="transactionTemplate" ></property> </bean> |
使用注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
//注解事务,放在类上,这个类所有的方法都应用 //如果,有某个方法不同,就在某个方法上加上注解事务就可以了 //@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false) public class AccountServiceImpl implements AccountService{ private AccountDao ad ; private TransactionTemplate tt; public void setAd(AccountDao ad) { this.ad = ad; } public void setTt(TransactionTemplate tt) { this.tt = tt; } @Override //注解事务 @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false) public void transfer(final Integer from, final Integer to, final Double money) { tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus arg0) { //减钱 ad.reduce(from, money); //int i = 1/0; //加钱 ad.add(to, money); } }); } } |
三大框架整合理论
导包
Hibernate
路径:hibernate/lib/required 下的所有jar文件
路径:hibernate/lib/jap 下的hibernate-jpa-2.1-api-1.0.0.Final.jar文件(JAP java的持久化规范)
数据库驱动:mysql-connector-java-5.1.7-bin.jar
Struts
路径:struts-2.3.24/apps/struts2-blank.war后缀改为zip解压后WEB-INF/lib下的所有包
注意:struts中的javassist与Hibernate重复,删除版本低的就可以了。
Struts整合Spring插件包:struts-2.3.24/lib/struts2-spring-plugin-2.3.24.jar
注意:这个包一旦导入,那么struts2在启动时就会寻找spring容器。找不到将会抛出异常。
Spring
基本:4+2
core|beans|context|expression|loggin|log4j
整合web:web包
spring-web
整合AOP:4个
spring-aop|spring-aspect|aop联盟|aop-weaving
整合jdbc&事务&连接池&ORM:4个
spring-jdbc|spring-tx|C3P0|spring-orm
junit4测试:test包
spring-test
标签库:standard.jar,jstl-1.2.jar
单独整合(配置)spring容器
创建spring配置文件,并导入约束(4个)
导入约束:beans|context|aop|tx
创建applicationContext.xml配置文件
1 2 3 4 5 6 7 |
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 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/aop http://www.springframework.org/schema/aop/spring-aop-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/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd "> </beans> |
配置web.xml:让spring随项目启动。
1 2 3 4 5 6 7 8 9 |
<!-- 让spring随web启动而创建的监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置spring配置文件位置参数 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> |
Ctrl+shift+T输入ContextloaderListener,选择输入的这个类,导入源码spring-web-4.2.4.RELEASE-sources.jar,找到ContextLoaderListener这个类,复制这个类的类全名。
在源码中类ContextLoaderListener extends ContextLoader中,Ctrl点击ContextLoader,查看源码,第二个常量CONFIG_LOCATION_PARAM = “contextConfigLocation”;,其中的值就是
测试
新建一个action类:UserAction
1 2 3 |
public class UserAction extends ActionSupport{ } |
到applicationContext.xml配置一下
1 |
<bean name="userAction" class="com.benz.action.UserAction"></bean> |
运行一下项目,控制台没报错则为成功。
单独整合(配置)Struts2
配置Struts2主文件
在src下创建struts.xml配置文件,并导入约束:在struts2-core包下有一个struts-2.3.dtd的约束文件,打开它,把里面的约束复制过来就可以了。
1 2 3 4 5 6 7 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> </struts> |
在web.xml中注册核心过滤器
1 2 3 4 5 6 7 8 9 10 11 |
<!-- 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> |
Ctrl+shift+T输入StrutsP就会有提示
测试
到struts.xml中配置一下UserAction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="crm" namespace="/" extends="struts-default"> <action name="userAction_*" class="com.benz.action.UserAction" method="{1}"> <result name="success">/success.jsp</result> </action> </package> </struts> |
运行一下项目,不报错就是成功。
整合struts2与spring
导包(已导):struts2-spring-plugin-2.3.24.jar
配置常量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!-- # struts.objectFactory = spring 将action的创建交给spring容器 struts.objectFactory.spring.autoWire = name spring负责装配Action依赖属性 --> <constant name="struts.objectFactory" value="spring"></constant> <package name="crm" namespace="/" extends="struts-default" > </package> </struts> |
整合方案一
struts2自己创建action,spring负责组装依赖属性。
不推荐理由:最好由spring完全管理action的生命周期。spring中功能才能应用到Action上。
1 2 3 4 5 6 |
<!-- 整合方案1:class属性上仍然配置action的完整类名 struts2仍然创建action,由spring负责组装Action中的依赖属性 --> <action name="userAction_*" class="com.benz.action.UserAction" method="{1}"> <result name="success">/success.jsp</result> </action> |
配置spring依赖属性
1 |
<bean name="userService" class="com.benz.service.Impl.userServiceImpl"></bean> |
整合方案二
spring负责创建action以及组装
1 2 3 4 5 6 7 8 9 |
<!-- 整合方案2:class属性上填写spring中action对象的BeanName 完全由spring管理action生命周期,包括Action的创建 注意:需要手动组装依赖属性 --> <action name="UserAction_*" class="userAction" method="{1}" > <result name="toHome" type="redirect" >/index.htm</result> <result name="error" >/login.jsp</result> </action> |
到spring配置action
1 2 3 4 5 |
<!-- 注意:Action对象作用范围一定是多例的,这样才符合struts2架构 --> <bean name="userAction" class="com.benz.action.UserAction" scope="prototype"> <!-- action所需的依赖 --> <property name="userService" ref="userService"></property> </bean> |
单独配置Hibernate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 数据库驱动 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 数据库url --> <property name="hibernate.connection.url">jdbc:mysql:///crm</property> <!-- 数据库连接用户名 --> <property name="hibernate.connection.username">root</property> <!-- 数据库连接密码 --> <property name="hibernate.connection.password">root</property> <!-- 数据库方言 注意: MYSQL在选择方言时,请选择最短的方言. --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 将hibernate生成的sql语句打印到控制台 --> <property name="hibernate.show_sql">true</property> <!-- 将hibernate生成的sql语句格式化(语法缩进) --> <property name="hibernate.format_sql">true</property> <!-- 自动导出表结构. 自动建表 --> <property name="hibernate.hbm2ddl.auto">update</property> <!--注意:事务隔离级别和绑定线程不要配置,Spring有自己处理的流程 <property name="hibernate.connection.isolation">4</property> <property name="hibernate.current_session_context_class">thread</property> --> <!-- 引入实体配置文件 --> <mapping resource="com/benz/domain/Customer.hbm.xml" /> <mapping resource="com/benz/domain/LinkMan.hbm.xml" /> <mapping resource="com/benz/domain/User.hbm.xml" /> </session-factory> </hibernate-configuration> |
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
@Test //单独测试hibernate public void fun1(){ Configuration conf = new Configuration().configure(); SessionFactory sf = conf.buildSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); //------------------------------------------------- User u = new User(); u.setUser_code("rose"); u.setUser_name("肉丝"); u.setUser_password("1234"); session.save(u); //------------------------------------------------- tx.commit(); session.close(); sf.close(); } |
整合hibernate与spring
整合原理:将sessionFactory对象交给spring容器管理。
到spring配置Hibernate
整合方案一(不推荐)
1 2 3 4 5 6 7 |
<!-- 将SessionFactory配置到spring容器中 --> <!-- 注意:class的路径:spring-orm-4.2.4.RELEASE.jar/org.springframework.orm.hibernate5/LocalSessionFactoryBean --> <!-- 加载配置方案1:仍然使用外部的hibernate.cfg.xml配置信息 --> <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" > <property name="configLocation" value="classpath:hibernate.cfg.xml" ></property> </bean> |
整合方案二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<!-- 将SessionFactory配置到spring容器中 --> <!-- 注意:class的路径:spring-orm-4.2.4.RELEASE.jar/org.springframework.orm.hibernate5/LocalSessionFactoryBean --> <!-- 加载配置方案2:在spring配置中放置hibernate配置信息 --> <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" > <!-- 配置hibernate基本信息 --> <property name="hibernateProperties"> <props> <!-- 必选配置 --> <prop key="hibernate.connection.driver_class" >com.mysql.jdbc.Driver</prop> <prop key="hibernate.connection.url" >jdbc:mysql:///crm</prop> <prop key="hibernate.connection.username" >root</prop> <prop key="hibernate.connection.password" >root</prop> <prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop> <!-- 可选配置 --> <prop key="hibernate.show_sql" >true</prop> <prop key="hibernate.format_sql" >true</prop> <prop key="hibernate.hbm2ddl.auto" >update</prop> </props> </property> <!-- 引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置 --> <property name="mappingDirectoryLocations" value="classpath:com/benz/domain" ></property> </bean> |
spring整合C3P0连接池
1.配置db.properties
1 2 3 4 |
jdbc.jdbcUrl=jdbc\:mysql\:///crm jdbc.driverClass=com.mysql.jdbc.Driver jdbc.user=root jdbc.password=root |
2.引入连接池到spring中
1 2 3 4 5 6 7 8 9 10 |
<!-- 读取db.properties文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 配置c3p0连接池 --> <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> |
3.将连接池注入到sessionFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" > <!-- 将连接池注入到sessionFactory, hibernate会通过连接池获得连接 --> <property name="dataSource" ref="dataSource" ></property> <!-- 配置hibernate基本信息 --> <property name="hibernateProperties"> <props> <!-- 必选配置 --> <prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop> <!-- 可选配置 --> <prop key="hibernate.show_sql" >true</prop> <prop key="hibernate.format_sql" >true</prop> <prop key="hibernate.hbm2ddl.auto" >update</prop> </props> </property> <!-- 引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置 --> <property name="mappingDirectoryLocations" value="classpath:cn/itcast/domain" ></property> </bean> |
HibernateTemplate模板操作数据库
创建userDao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
//HibernateDaoSupport 为dao注入sessionFactory public class UserDaoImpl extends HibernateDaoSupport implements UserDao { @Override public User getByUserCode(final String usercode) { //HQL return getHibernateTemplate().execute(new HibernateCallback<User>() { @Override public User doInHibernate(Session session) throws HibernateException { String hql = "from User where user_code = ? "; Query query = session.createQuery(hql); query.setParameter(0, usercode); User user = (User) query.uniqueResult(); return user; } }); //Criteria /*DetachedCriteria dc = DetachedCriteria.forClass(User.class); dc.add(Restrictions.eq("user_code", usercode)); List<User> list = (List<User>) getHibernateTemplate().findByCriteria(dc); if(list != null && list.size()>0){ return list.get(0); }else{ return null; }*/ } @Override public void save(User u) { getHibernateTemplate().save(u); } } |
spring 配置注入sessionFactory
1 2 3 4 5 |
<!-- dao --> <bean name="userDao" class="com.benz.dao.impl.UserDaoImpl" > <!-- 注入sessionFactory --> <property name="sessionFactory" ref="sessionFactory" ></property> </bean> |
测试
1 2 3 4 5 6 7 8 9 10 |
@Resource(name="userDao") private UserDao ud; @Test //测试Dao Hibernate模板 public void fun3(){ User u = ud.getByUserCode("tom"); System.out.println(u); } |
整合AOP事务
配置核心事务管理器
1 2 3 4 |
<!-- 核心事务管理器 --> <bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" > <property name="sessionFactory" ref="sessionFactory" ></property> </bean> |
配置方式一:xml配置AOP事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!-- 配置通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager" > <tx:attributes> <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:attributes> </tx:advice> <!-- 配置将通知织入目标对象 配置切点 配置切面 --> <aop:config> <aop:pointcut expression="execution(* com.benz.service.impl.*ServiceImpl.*(..))" id="txPc"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" /> </aop:config> |
配置方式二:注解配置AOP事务
开启注解配置事务
1 2 |
<!-- 开启注解事务 --> <tx:annotation-driven transaction-manager="transactionManager" /> |
service类中使用注解
1 2 3 4 5 |
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true) public class UserServiceImpl implements UserService{ } |
扩大session作用范围
为了避免使用懒加载时出现no-session问题,需要扩大session的作用范围
配置filter
1 2 3 4 5 6 7 8 9 10 11 |
<!-- 扩大session作用范围 注意: 任何filter一定要在struts的filter之前调用 --> <filter> <filter-name>openSessionInView</filter-name> <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openSessionInView</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |