- 概念
- IOC原理及入门案例
- Spring的bean管理(xml方式)
- Spring的bean管理(注解方式)
- IOC和DI
- AOP原理
- AOP操作术语
- Spring的aop操作(xml方式)
- Spring的aop操作(注解方式)
- JdbcTemplate基本操作
- Spring中配置jdbcTemplate
- Spring中配置事物
- Spring管理Web项目原理
概念
Spring makes Java simple, modern, productive, reactive, cloud-ready.
Spring是一个开源的轻量级的一站式框架。其核心为:
- AOP:面向切面编程。简单理解面向切面编程,就是扩展功能不需要修改源代码;
- IOC:控制反转。创建对象不再需要New来创建,而是交由Spring去创建;
之所以说Spring是一站式框架,是因为spring在javaee三层框架中都提供了不同技术:
- web层:springMVC;
- service层:主要使用spring的ioc;
- dao层:提供了jdbcTemplate;
IOC原理及入门案例
Spring中IOC操作有两种方式:xml配置方式 和 注解方式。
Spring中ioc的实现底层主要依赖四种技术:
- xml配置文件;
- dom4j解析配置文件;
- 工厂设计模式;
- 反射;
现假如有UserService,内有add方法,要在Servlet中调用该方法,ioc伪代码实现:
// UserService
public class UserService {
public void add(){};
}
// 1. 创建xml配置文件,配置对象类
<bean id="userService" class="cn.demo.UserService" />
// 2. 创建工厂类,类中使用dom4j加反射得到UserService实例
public class UserServiceFactory {
public static UserService getUserServie(){
// 3. 使用dom4j解析xml,根据id得到class的值
// String classValue = "class属性值";
// 4. 使用反射创建实例
Class clazz = Class.forName(classValue);
UserService userService = clazz.newInstance();
return userService;
}
}
// 使用工厂得到实例,调用方法即可
spring IOC入门案例:
- 引入依赖;
- 创建类和方法;
- 创建spring配置文件;
- 编码测试;
引入依赖:这里为IOC入门体验,因此只需引入spring核心包即可,包括Beans、Core、Context、SpEL。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.adoredu</groupId>
<artifactId>spring-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
创建类:
package cn.adoredu.ioc;
public class UserService {
public void add() {
System.out.println("add...");
}
}
创建spring配置文件,建议放至src下并叫applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="cn.adoredu.ioc.UserService"></bean>
</beans>
测试代码:
package cn.adoredu.ioc;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestIOC {
@Test
public void test() {
// 1. 加载配置文件,创建对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 得到配置创建的对象
UserService userService = (UserService) context.getBean("userService");
// 查看结果
System.out.println(userService);
userService.add();
}
}
Spring的bean管理(xml方式)
- Bean实例化的三种方式:
- 使用无参数构造创建
<!-- 实际开发中最常用的实例化方式,上述配置实例化bean就是使用无参构造创建,如果类中没有无参构造函数会报错`No default constructor found;`,无法实例化对象;-->
<bean id="userService" class="cn.adoredu.ioc.UserService"></bean>
- 使用静态工厂创建
// 创建静态方法工厂类
package cn.adoredu.ioc;
public class BeanFactory {
// 静态方法
public static UserService getUserService() {
return new UserService();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 方式一:无参构造 -->
<!-- <bean id="userService" class="cn.adoredu.ioc.UserService"></bean> -->
<!-- 方式二:使用静态工厂创建 -->
<bean id="userService" class="cn.adoredu.ioc.BeanFactory" factory-method="getUserService"></bean>
</beans>
- 使用实例工厂创建
package cn.adoredu.ioc;
public class BeanFactory2 {
// 普通方法
public UserService getUserService() {
return new UserService();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 方式一:无参构造 -->
<!-- <bean id="userService" class="cn.adoredu.ioc.UserService"></bean> -->
<!-- 方式二:使用静态工厂创建 -->
<!-- <bean id="userService" class="cn.adoredu.ioc.BeanFactory" factory-method="getUserService"></bean> -->
<!-- 方式三:使用实例工厂创建 -->
<bean id="beanFactory" class="cn.adoredu.ioc.BeanFactory2"></bean>
<bean id="userService" factory-bean="beanFactory" factory-method="getUserService"></bean>
</beans>
- Bean标签常用属性
-
id:bean标识, 可以任意,但不能包含特殊字符;
-
class:要创建对象所在类的全路径;
-
name:和id作用一样,但可以包含特殊字符。版本遗留问题,现一般使用id即可;
-
scope:
- singleton:默认值,单实例;
- prototype:多实例;
- request:创建对象,把对象放在request域里面;
- session:创建对象,把对象放在session域里面;
- globalSession:创建对象,把对象放在globalSession域里面;
理解singleton和prototype,多次调用context.getBean()方法得到的对象是同一个还是多个。
- 属性注入
属性注入是指在创建对象实例时,给其属性设置值。
给普通类设置属性值一般有三种方式:
- 使用set方法注入:
public class User {
private String name;
public void setName(String name) {
this.name = name;
}
}
- 使用构造方法注入:
public class User {
private String name;
public User(String name) {
this.name = name;
}
}
- 使用接口注入:
public Interface UserDao {
void setName(String name);
}
...
public class User Implenments UserDao {
private String name;
public void setname(String name) {
this.name = name;
}
}
spring中属性注入主要有两种方式:
- set方法注入(常用)
package cn.adoredu.ioc.bean;
public class User {
private String name;
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println(this.name);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用set方法注入属性 -->
<bean id="user" class="cn.adoredu.ioc.bean.User">
<property name="name" value="Jerry"></property>
</bean>
</beans>
package cn.adoredu.ioc;
import cn.adoredu.ioc.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestIOC {
@Test
public void test() {
// 1. 加载配置文件,创建对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2. 得到配置创建的对象
User user = (User) context.getBean("user");
user.show();
}
}
- 有参数构造注入
// 实体类
package cn.adoredu.ioc.bean;
public class User {
private String name;
public User(String name) {
this.name = name;
}
public void show() {
System.out.println(this.name);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用有参构造注入属性 -->
<bean id="user" class="cn.adoredu.ioc.bean.User">
<constructor-arg name="name" value="Tom"></constructor-arg>
</bean>
</beans>
使用set方式注入对象类型:
package cn.adoredu.ioc;
public class UserDao {
public void add() {
System.out.println("userDao add...");
}
}
package cn.adoredu.ioc;
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add() {
System.out.println("userService add...");
userDao.add();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用set方式注入对象类型 -->
<bean id="userDao" class="cn.adoredu.ioc.UserDao"></bean>
<bean id="userService" class="cn.adoredu.ioc.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
使用set方式注入复杂类型:
package cn.adoredu.ioc;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class UserService {
private String[] arrs;
private List<String> list;
private Map<String, String> map;
private Properties properties;
public void setArrs(String[] arrs) {
this.arrs = arrs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void add() {
System.out.println("arrs:"+arrs);
System.out.println("list:"+list);
System.out.println("map:"+map);
System.out.println("properties:"+properties);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 注入复杂类型 -->
<bean id="userService" class="cn.adoredu.ioc.UserService">
<property name="arrs">
<list>
<value>java</value>
<value>python</value>
</list>
</property>
<property name="list">
<list>
<value>vue</value>
<value>react</value>
</list>
</property>
<property name="map">
<map>
<entry key="a" value="aa"></entry>
<entry key="b" value="bb"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="c">cc</prop>
<prop key="d">dd</prop>
</props>
</property>
</bean>
</beans>
Spring的bean管理(注解方式)
引入依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.adoredu</groupId>
<artifactId>spring-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!--使用注解需要spring-aop-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
创建配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 注意约束不一样 -->
<!-- 开启注解扫描
会扫描类、属性、方法上的注解
-->
<context:component-scan base-package="cn.adoredu.anno"></context:component-scan>
<!-- 只会扫描属性上注解 -->
<!-- <context:annotation-config></context:annotation-config>-->
</beans>
- 注解创建对象
package cn.adoredu.anno;
import org.springframework.stereotype.Component;
@Component(value = "user") // 相当于<bean id="user" class=""></bean>
//@Component("user") 属性为value时可以省略
//@Scope(value = "prototype")
public class User {
public void add() {
System.out.println("add...");
}
}
测试:
package cn.adoredu.anno;
import cn.adoredu.anno.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestANNO {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
user.add();
}
}
- 注解方式注入属性
package cn.adoredu.anno;
import org.springframework.stereotype.Component;
@Component("userDao")
public class UserDao {
public void add() {
System.out.println("userDao add...");
}
}
package cn.adoredu.anno;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("userService")
public class UserService {
@Autowired
private UserDao userDao;
// 注解方式不需要定义set方法
public void add() {
System.out.println("userServive add...");
userDao.add();
}
}
说明:@Autowired是通过类型注入,即与UserDao上@Component的value值无关。还可以通过@Resource方式注入属性,此时name属性值必须为对象的@Component的value值:@Component(name=”userDao”)。
IOC和DI
IOC:Inversion of Control,控制反转,把对象的创建交由spring管理;
DI:Dependency Injection,依赖注入,给类的属性设置值;
DI需要在IOC的基础上完成。
AOP原理
APP底层使用动态代理方式实现。分两种情况:
- 有接口:使用jdk动态代理,创建接口实现类的代理对象;
- 无接口:使用cglib动态代理,创建类的子类的代理对象;
AOP操作术语
- JoinPoint:连接点。一个类中所有可以被增强的方法都称为连接点;
- PointCut:切入点。类中真正被增强的方法叫切入点;
- Advice:增强,也叫通知。指实际扩展的逻辑,分为
- 前置通知:方法前执行;
- 后置通知:方法后执行;
- 异常通知:异常时执行;
- 最终通知:后置之后执行;
- 环绕通知:之前和之后,如统计方法执行时间时;
- Aspect:切面。指把增强应用到切入点(的过程);
Spring的aop操作(xml方式)
Spring里使用aspectJ实现aop的操作。AspectJ本身不是Spring的一部分,它是一个面向切面的框架。Spring2.0以后增加了对AspectJ的支持。
使用AspectJ实现aop有两种方式:
- xml配置;
- 注解;
引入依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.adoredu</groupId>
<artifactId>spring-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
创建类:
package cn.adoredu.aop;
import org.aspectj.lang.ProceedingJoinPoint;
public class BookAdvice {
public void before() {
System.out.println("前置增强");
}
public void after() {
System.out.println("后置增强");
}
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法之前");
joinPoint.proceed();
System.out.println("方法之后");
}
}
package cn.adoredu.aop;
public class Book {
public void add() {
System.out.println("add...");
}
}
配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1. 配置对象 -->
<bean id="book" class="cn.adoredu.aop.Book"></bean>
<bean id="bookAdvice" class="cn.adoredu.aop.BookAdvice"></bean>
<!-- 2. 配置aop操作 -->
<aop:config>
<!-- 2.1 配置切入点 -->
<aop:pointcut id="pointCut" expression="execution(* cn.adoredu.aop.Book.*(..))"/>
<!-- 2.2 配置切面 -->
<aop:aspect ref="bookAdvice">
<!-- 配置增强类型 -->
<aop:before method="before" pointcut-ref="pointCut" />
<aop:after-returning method="after" pointcut-ref="pointCut" />
<aop:around method="around" pointcut-ref="pointCut" />
</aop:aspect>
</aop:config>
</beans>
常用的表达时:
- execution(* cn.adoredu.aop.Book.add(..)):修饰符 方法全路径(任意参数);
- execution(* cn.adoredu.aop.Book.*(..));
- execution(* *.*(..));
- execution(* save*(..))
Spring的aop操作(注解方式)
配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置对象 -->
<bean id="book" class="cn.adoredu.aop.Book"></bean>
<bean id="bookAdvice" class="cn.adoredu.aop.BookAdvice"></bean>
<!-- 开启aop操作 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
类:
package cn.adoredu.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BookAdvice {
@Before(value = "execution(* cn.adoredu.aop.Book.*(..))")
public void before() {
System.out.println("前置增强");
}
@AfterReturning("execution(* *.*(..))")
public void after() {
System.out.println("后置增强");
}
@Around("execution(* *.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法之前");
joinPoint.proceed();
System.out.println("方法之后");
}
}
JdbcTemplate基本操作
添加依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- 别忘了数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
步骤:
- 创建对象,设置数据库信息;
- 创建jdbcTemplate对象,设置数据源;
- 调用jdbcTemplate对象里方法实现操作;
测试类:
package cn.adoredu.jdbc;
import cn.adoredu.ioc.bean.User;
import org.junit.Before;
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
public class TestJDBC {
private JdbcTemplate jdbcTemplate;
@Before
public void init() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring-test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
jdbcTemplate = new JdbcTemplate(dataSource);
}
@Test
public void testInsert() {
String sql = "INSERT INTO user VALUES (?, ?, ?)";
int rows = jdbcTemplate.update(sql, 1, "admin", "123456");
System.out.println(rows);
}
@Test
public void testUpdate() {
String sql = "UPDATE user SET password=? WHERE username=?";
int rows = jdbcTemplate.update(sql, "654321", "admin");
System.out.println(rows);
}
@Test
public void testDelete() {
String sql = "DELETE FROM user WHERE username=?";
int rows = jdbcTemplate.update(sql, "admin");
System.out.println(rows);
}
@Test
public void testQuery() {
// 查询返回一个值
String sql = "SELECT COUNT(*) FROM user";
int count = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println(count);
}
@Test
public void testQuery2() {
// 查询一个对象
String sql = "SELECT * FROM user WHERE username=?";
User user = jdbcTemplate.queryForObject(sql, new MyRowMapper(), "admin");
System.out.println(user);
}
@Test
public void testQuery3() {
// 查询返回对象list
String sql = "SELECT * FROM user";
List<User> userList = jdbcTemplate.query(sql, new MyRowMapper());
System.out.println(userList);
}
}
class MyRowMapper implements RowMapper<User> {
public User mapRow(ResultSet resultSet, int i) throws SQLException {
// 1. 从结果集中得到数据
String username = resultSet.getString("username");
String password = resultSet.getString("password");
// 2. 把数据封装到对象
User user = new User();
user.setUsername(username);
user.setPassword(password);
return user;
}
}
使用jdbcTemplate和dbutils非常类似。不同的是查询时的RowMapper需要手动实现。
Spring中配置jdbcTemplate
以使用c3p0连接池为例:
添加依赖:
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.1</version>
</dependency>
实际上就是要把数据源的代码(如下)放在配置文件,交由Spring来创建(使用c3p0连接池):
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql:///spring-test");
dataSource.setUser("root");
dataSource.setPassword("123456");
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置c3p0连接池 -->
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="dbc:mysql:///spring-test"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="userService" class="cn.adoredu.c3p0.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="cn.adoredu.c3p0.UserDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="datasource"></property>
</bean>
</beans>
Spring中配置事物
Spring中使用事物有两种方式:编程式事物和声明式事物,常用的是声明式事物。而声明式事物有xml配置和注解两种实现方式。
Spring中实现事物需要配置事务管理器。Spring对不同的dao层框架提供了不同的事物管理器接口(PlatformTransactionManager)实现类,对jdbcTemplate提供的实现类为DataSourceTransactionManager。
- xml配置事物
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置c3p0连接池 -->
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///spring-test"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="datasource"></property>
</bean>
<bean id="orderService" class="cn.adoredu.tx.OrderService">
<property name="orderDao" ref="orderDao"></property>
</bean>
<bean id="orderDao" class="cn.adoredu.tx.OrderDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- 1. 配置事物管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<!-- 2. 配置事物增强 -->
<!-- 指定事物管理器 -->
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
<!-- 事物操作 -->
<tx:attributes>
<!-- 设置事物操作的方法匹配规则 -->
<tx:method name="account*" />
</tx:attributes>
</tx:advice>
<!-- 3. 配置切入点和切面 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut id="pointcut" expression="execution(* cn.adoredu.tx.OrderService.*(..))"/>
<!-- 切面 -->
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="pointcut" />
</aop:config>
</beans>
- 注解实现事物
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置c3p0连接池 -->
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///spring-test"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="datasource"></property>
</bean>
<bean id="orderService" class="cn.adoredu.tx.OrderService">
<property name="orderDao" ref="orderDao"></property>
</bean>
<bean id="orderDao" class="cn.adoredu.tx.OrderDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- 1. 配置事物管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<!-- 2. 开启事物注解 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
package cn.adoredu.tx;
import org.springframework.transaction.annotation.Transactional;
// 3. 添加@Transactional注解
@Transactional
public class OrderService {
private OrderDao orderDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void account() {
orderDao.reduceMoney();
int a = 10 / 0; // 模拟异常
orderDao.addMoney();
}
}
Spring管理Web项目原理
- 服务器启动时会为每个项目创建一个ServletContext对象;
- 使用监听器,监听在ServletContext对象创建时,加载配置文件,创建对象;
- 把创建出的对象放在ServletContext域对象中(setAttribute()方法);
- 获取对象时到ServletContext域对象中获取即可(getAttribute()方法);
Spring已经实现管理web项目方式(依赖spring-web包)。只需要在web.xml中进行配置:
...
<!-- 指定spring配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath: applicationContext.xml</param-value>
</context-param>
<!-- 配置监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
...