1.什么是Spring
Spring 分层的Java SE/EE 应用轻量级框架,以IOC ( Inversion of Controll控制反转)
和AOP(Aspect oriented Programming,面向切面编程,本质是动态代理,不修改源码的情况下进行功能增强)为内核 。
提供了
2.Spring 体系结构
3.耦合性问题:
* 耦合性:程序之间的依赖性。
* 编译期依赖:编译时必须提供依赖的类,否则编译不通过。应当避免编译期依赖
* 运行期依赖:运行时必须提供依赖的类,否则不能运行
* 耦合性越强,维护成本就越高
* 开发时要求:高内聚,低耦合
4.耦合性问题现象
* 在web开发中,服务端通常分为三层:web层、service层、dao层
* web层调用service层完成功能:需要new一个Service对象
* service层调用dao层操作数据库:需要new一个dao对象
* 三层之间的耦合性比较强:存在编译期依赖
* service里写死了创建某一个dao对象:一旦dao对象换了,就需要修改service的源码
* web里写死了创建某一个service对象:一旦service对象换了,就需要修改web的源码
5.解耦思路
方法1:可以使用反射技术,代替`new`创建对象,避免编译期依赖。
Class clazz = Class.forName("全限定类名");
Object obj = clazz.newInstance();
方法2:再把全限定类名提取到配置文件中(xml或properties),读取配置文件信息来反射创建对象
//读取配置文件,得到要创建对象的全限定类名;再通过反射技术创建对象
String className = ...;
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();
6.使用工厂模式解耦
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
dao层:
public interface UserDao {
void save();
}
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDaoImpl.save......");
}
}
service层:
public interface UserService {
void save();
}
public class UserServiceImpl implements UserService {
/**
* 存在编译期依赖:如果没有UserDaoImpl,代码编译是不通过的。
* 要避免编译期依赖,减少运行期依赖
* 解决思路:
* 1. 使用反射技术代替new
* 2. 提取配置文件
*/
//private UserDao userDao = new UserDaoImpl();
private UserDao userDao = (UserDao) BeanFactory.getBean("userDao");
@Override
public void save() {
userDao.save();
}
}
配置文件beans.properties
userDao=com.zengjx.dao.impl.UserDaoImpl
工厂类BeanFactory
public class BeanFactory {
private static Map<String, Object> map = new HashMap<>();
static {
//类加载时,读取properties文件,把其中所有的bean都创建对象,放到一个容器里
//当需要使用时,直接从容器中获取即可
try {
//1.读取配置文件
ResourceBundle bundle = ResourceBundle.getBundle("beans");
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()) {
String id = keys.nextElement();
String className = bundle.getString(id);
Class clazz = Class.forName(className);
Object object = clazz.newInstance();
map.put(id, object);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object getBean(String id){
return map.get(id);
}
}
总结:
* 解耦的思路:解决编译期依赖
1. 生成对象时,使用反射代替`new`
2. 配置信息放到配置文件里
* bean容器:
* BeanFactory里增加了一个Map,把第个bean对象都放到Map里。
* 需要使用时,只要直接从Map里获取即可,不需要每次都创建
* Spring解耦的时候:
* 我们需要做的事情:
* 编写Service、dao类(bean)
* 编写配置文件(xml)
* Spring做的事情:
* 提供工厂类,我们直接调用Spring的工厂,获取bean对象,而不用自己创建
7.IOC 思想
* `IoC`:Inversion of Control,控制反转。是指 把创建对象的控制权交给框架:要想得到一个对象,由原来的主动创建对象,变成自己被动接收 框架创建的对象。
* `IoC`是Spring的核心思想之一
* 作用:用于降低程序间的耦合性(耦合性不能彻底解除,只能降低)
8. 控制反转入门
#### 1. 需求描述
* 有`UserDao`接口和`UserDaoImpl`实现类
* 通过Spring容器得到`UserDaoImpl`的实例对象(IoC方式)
#### 2. 开发步骤
1. 创建Maven项目,导入依赖坐标:Spring的依赖坐标
2. 编写dao接口`UserDao`及实现`UserDaoImpl`
3. 创建Spring核心配置文件,并配置`UserDaoImpl`
4. 使用Spring的API,获取Bean实例对象
maven 坐标
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
dao 层:
public interface UserDao {
void save();
}
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDaoImpl.save......");
}
}
创建Spring核心配置文件,并配置UserDaoImpl
配置文件名称,通常叫`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">
<!-- 配置UserDaoImpl -->
<bean id="userDao" class="com.zengjx.dao.impl.UserDaoImpl"></bean>
</beans>
使用Spring的API ,获得Bean 实例对象
public class SpringIocQuickStartTest {
@Test
public void test(){
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = context.getBean("userDao", UserDao.class);
userDao.save();
}
}
步骤总结:
1. 创建Maven项目,导入依赖:`spring-context`
2. 创建dao接口和实现类
3. 创建配置文件:通常是`applicationContext.xml`
```xml
<bean id="唯一标识" class="全限定类名"></bean>
```
4. 测试:从Spring容器里获取bean对象
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
Object bean = app.getBean("bean的唯一标识");
9.配置文件解释
-
用于配置:把对象交给Spring进行控制
-
默认情况下,Spring是调用类的无参构造来创建对象的;如果没有无参构造,则不能创建成功
<bean id="userDao" class="com.zengjx.dao.impl.UserDaoImpl"></bean>
* `id`:唯一标识
* `class`:bean的全限定类名
> 了解:bean的id和name的区别
>
> 1. 一个bean只能有一个id;一个bean可以有多个name
> 2. bean的name值:多个name之间以`,` `;` `空格 ` 隔开,第1个name作为id,其它作为别名
bean 标签的作用范围
<bean id="userDao" class="com.zengjx.dao.impl.UserDaoImpl" scope="singleton"></bean>
* scope属性取值如下:
| 取值 | 说明 |
| --------------- | ------------------------------------------------------------ |
| `singleton` | 默认,表示单例的,一个Spring容器里,只有一个该bean对象 |
| `prototype` | 多例的,一个Spring容器里,有多个该bean对象 |
| `request` | web项目里,Spring创建的bean对象将放到`request`域中 |
| `session` | web项目里,Spring创建的bean对象将放到`session`域中 |
| `globalSession` | web项目里,应用在Portlet环境/集群环境;如果没有Portlet/集群环境,那么globalSession相当于session(新版本中已删除) |
10.不同scope的bean,生命周期
* singleton:bean的生命周期和Spring容器的生命周期相同
* 整个Spring容器中,只有一个bean对象
* 何时创建:加载Spring配置文件,初始化Spring容器时,bean对象创建
* 何时销毁:Spring容器销毁时,bean对象销毁
* prototype:bean的生命周期和Spring容器无关。Spring创建bean对象之后,交给JVM管理了
* 整个Spring容器中,有多个bean对象
* 何时创建:调用`getBean`方法获取bean对象时,bean对象创建
* 何时销毁:对象长时间不用时,垃圾回收
11.bean
的生命周期相关方法的配置(了解)
<bean id="userDao" class="com.zenjgx.dao.impl.UserDaoImpl"
init-method="" destroy-method=""></bean>
* `init-method`:指定类中初始化方法名称,该方法将在bean对象被创建时执行
* `destroy-method`:指定类中销毁方法名称,该方法将在bean对象被销毁时执行
> 注意:在单元测试里,Spring容器显式关闭时,才会执行destroy-method指定的方法
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = context.getBean("userDao", UserDao.class);
//显式的关闭Spring容器
((ClassPathXmlApplicationContext)context).close();
12.bean实例化的三种方式
DataSource dataSource = DruidDataSourceFactory.createDataSource();
-
无参构造方法实例化:默认的,让Spring调用bean的无参构造,生成bean实例对象
-
工厂静态方法实例化:让Spring调用一个工厂类的静态方法,得到一个bean实例对象
-
工厂非静态方法实例化(实例化方法):让Spring调用一个工厂对象的非静态方法,得到一个bean实例对象
###### 2.1 无参构造方法实例化
```xml
<bean id="userDao" class="com.zengjx.dao.impl.UserDaoImpl"></bean>
```
###### 2.2 工厂静态方法实例化
* 工厂类如下:`com.zengjx.factory.StaticFactory`
```java
public class StaticFactory{
public static UserDao createUserDao(){
return new UserDaoImpl();
}
}
```
* 配置如下:
```xml
<bean id="userDao" class="com.zengjx.factory.StaticFactory"
factory-method="createUserDao"></bean>
```
###### 2.3 工厂非静态方法实例化
* 工厂类如下:`com.zengjx.factory.InstanceFactory`
```java
public class InstanceFactory{
public UserDao createUserDao(){
return new UserDaoImpl();
}
}
```
* 配置如下:
```xml
<!-- 先配置工厂 -->
<bean id="instanceFactory" class="com.zengjx.factory.InstanceFactory"></bean>
<!-- 再配置UserDao -->
<bean id="userDao" factory-bean="instanceFactory" factory-method="createUserDao"></bean>
```
13. IOC总结
### IoC小结
* IoC:用于解耦的,控制反转
* 如果我们需要一个对象,Spring会帮我们创建对象,交给我们使用
* bean的配置:告诉Spring创建什么样的对象
* 基本配置:`<bean id="唯一标识" class="全限定类名"/>`
* 作用范围:`<bean id="唯一标识" class="全限定类名" scope="作用范围"/>`
* `singleton`:单例模式。一个Spring容器里只有一个该bean的对象
* 何时创建:Spring容器初始化时,创建的
* 何时销毁:Spring容器关闭时,销毁的
* `prototype`:多例模式。一个Spring容器里有多个该bean的对象(Spring创建完,交给JVM管理)
* 何时创建:获取bean对象时,创建的
* 何时销毁:长时间不用,垃圾回收
* 生命周期的方法:`<bean id="唯一标识" class="全限定类名" init-method="初始化方法" destroy-method="销毁方法"/>`
* `init-method`:把一个方法设置为初始化方法,这个方法会在bean对象被创建时执行一次
* `destroy-method`:把一个 方法设置为销毁方法,这个方法会在bean对象被销毁时执行一次
> 如果bean是多例的,对象销毁进也不会执行destroy-method
* bean实例化的三种方式:告诉Spring如何创建对象
* 默认的无参构造:Spring调用无参构造,生成bean的实例对象
* 静态工厂方式:Spring调用工厂类的静态方法,生成bean的实例对象
* 实例化工厂方式:Spring对象工厂对象的非静态方法,生成bean的实例对象
14.依赖注入
* 依赖注入:`Dependency Injection`,是Spring的Ioc核心的具体实现。
* 类里依赖什么,由Spring注入(提供)什么
* 我们需要进行配置:告诉Spring,依赖什么
我们通过Ioc把bean对象交给了Spring容器进行管理,降低了耦合性。
但是耦合性不能彻底消除,bean之间还是有一些依赖关系。比如:业务层userService要依赖于持久层userDao。
这样的依赖关系,可以交给Spring帮我们进行依赖的注入,而不用我们自己注入依赖
### 快速入门
#### 1. 需求描述
* 有dao层:`UserDao`和`UserDaoImpl`
* 有service层:`UserService`和`UserServiceImpl`
* `UserServiceImpl`中的方法依赖于`UserDaoImpl`
* 使用Spring,把`UserDaoImpl`注入给`UserServiceImpl`
#### 2. 开发步骤
1. 创建Maven项目,导入依赖坐标
2. 编写dao层`UserDao`及`UserDaoImpl`、service层`UserService`和`UserServiceImpl`
3. 创建Spring核心配置文件,并配置bean和依赖注入
4. 使用Spring的API,测试
#### 3. 需求实现
##### 1. 创建Maven项目,导入依赖
```xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
```
##### 2. 编写dao层和service层代码
* dao层接口`UserDao`
```java
public interface UserDao {
void save();
}
```
* dao层实现类`UserDaoImpl`
```java
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDaoImpl.save......");
}
}
```
* service层接口`UserService`
```java
public interface UserService {
void save();
}
```
* service层实现类`UserServiceImpl`
```java
public class UserServiceImpl implements UserService {
//依赖于dao层的UserDao,定义一个成员变量
private UserDao userDao;
@Override
public void save() {
userDao.save();
}
//提供userDao的get/set方法
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
```
##### 3. 创建Spring核心配置文件,并配置bean和依赖注入
```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">
<!--配置UserDao-->
<bean id="userDao" class="com.zengjx.dao.impl.UserDaoImpl"></bean>
<!--配置UserService-->
<bean id="userService" class="com.zengjx.service.impl.UserServiceImpl">
<!--把userDao注入给userService的属性-->
<property name="userDao" ref="userDao"/>
</bean>
</beans>
```
##### 4. 使用Spring的API,测试
```java
public class UserTest {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.save();
}
}
```
#### 4. 小结
1. 创建Maven项目,导入依赖:`spring-context`
2. 创建类:`UserService`和`UserDao` 接口及实现类
* Service依赖于dao,要求:Service里有dao的引用、set方法
3. 创建配置文件:声明bean之间的依赖关联
```xml
<bean>
<property name="属性名称" ref="要注入的bean对象的id"/>
</bean>
```
4. 测试
15.三种注入方式
#### 2.1 set方法注入
##### 1) 介绍
在类中提供需要注入的成员(依赖项)的set方法,在配置文件中注入属性的值
```xml
<bean id="" class="">
<property name="属性名" value="属性值"></property>
<property name="属性名" ref="bean的id"></property>
</bean>
```
* `property`标签:用在bean标签内部,表示要给某一属性注入数据
* `name`:属性名称
* `value`:要注入的属性值,注入简单类型值
* `ref`:要注入的属性值,注入其它bean对象
> 优势:创建bean对象时没有明确的限制,可以使用无参构造直接创建
>
> 缺点:如果某个成员必须有值,则获取对象时,有可能set方法未执行
2.2 构造方法注入
##### 1) 介绍
在类中提供构造方法,构造方法的每个参数就是一个依赖项,通过构造方法给依赖项注入值。
```xml
<bean id="" class="">
<constructor-arg name="构造参数名称" value="构造参数的值"></constructor-arg>
<constructor-arg name="构造参数名称" ref="bean的id"></constructor-arg>
</bean>
```
* `name`:构造参数的名称
* `type`:构造参数的类型
* `index`:构造参数的索引
* `value`:要注入的值,注入简单类型值
* `ref`:要注入的值,注入其它bean对象
> 优势:在获取bean对象时,注入数据是必须的操作,否则无法创建成功。
>
> 缺点:改变了bean对象的实例化方式,如果在创建对象时用不到这些数据,也必须要提供
<!--
2. 构造方法注入
要求:bean类里提供有参构造,每个构造参数就是一个依赖项
配置:使用constructor-arg标签,注入值
name:构造参数名称
value:注入的简单值
ref:注入的其它bean对象
优点:必须的依赖项,必须注入。否则会报错
缺点:不太灵活。如果有些依赖项是非必须的,也必须注入
-->
<!--<bean id="userService" class="com.zengjx.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="name" value="jerry"/>
</bean>-->
#### 2.3 p名称空间注入(本质仍然是set方法)
##### 1) 介绍
依赖项要提供set方法, 在xml中引入p名称空间的约束
然后通过`p:属性名称=""`来注入简单数据、使用`p:属性名称-ref=""`注入其它bean对象,它的本质仍然是set方法注入
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="" class="" p:属性名="简单值" p:属性名-ref="bean的id"></bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
3. p名称空间注入
要求:bean类里依赖项必须提供set方法; XML里必须增加 p名称空间引入
-->
<!--<bean id="userService" class="com.itheima.service.impl.UserServiceImpl" p:userDao-ref="userDao" p:name="jack"></bean>-->
16.集合注入给数组、List、Set、Map等注入数据
public class UserDaoImpl implements UserDao {
private String[] arr;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties properties;
public String[] getArr() {
return arr;
}
public void setArr(String[] arr) {
this.arr = arr;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void show(){
System.out.println(Arrays.toString(this.arr));
System.out.println(this.list);
System.out.println(this.set);
System.out.println(this.map);
System.out.println(this.properties);
}
}
配置注入数据
-
注入数组:
array
-
注入List:
list
-
注入Set:
set
-
注入Map:
map
-
注入Properties:
props
<bean id="userDao" class="com.zengjx.dao.impl.UserDaoImpl">
<!--给数组注入数据-->
<property name="arr">
<array>
<value>a</value>
<value>b</value>
<value>c</value>
</array>
</property>
<!--给list注入数据-->
<property name="list">
<list>
<value>a1</value>
<value>b1</value>
<value>c1</value>
</list>
</property>
<!--给set注入数据-->
<property name="set">
<set>
<value>a2</value>
<value>b2</value>
<value>c2</value>
</set>
</property>
<!--给map注入数据-->
<property name="map">
<map>
<entry key="a3" value="a3"/>
<entry key="b3" value="b3"/>
<entry key="c3" value="c3"/>
</map>
</property>
<!--给properties注入数据-->
<property name="properties">
<props>
<prop key="a4">a4</prop>
<prop key="b4">b4</prop>
<prop key="c4">c4</prop>
</props>
</property>
</bean>
所有单列结构的数据集合,标签可以互换使用。例如:List、Set、数组等
所有键值对结构的数据集合,标签可以互换使用。例如:Map、Properties等
17.ApplicationContext的继承体系
ApplicationContext
:接口,代表应用上下文,可以通过其实例对象获取Spring容器中的bean对象
18.ApplicationContext 实现类
### 2. `ApplicationContext`的实现类
#### 2.1 `ClassPathXmlApplicationContext`
* 是从类加载路径里,加载xml配置文件的
* 什么是类加载路径:代码编译之后的那个classes文件夹,
* 开发中可以认为Maven项目的:Java文件夹、resources文件夹,都是类加载路径
#### 2.2 `FileSystemXmlApplicationContext`
* 从磁盘路径里,加载xml配置文件的
#### 2.3 `AnnotationConfigApplicationContext`
* 用注解配置Spring时,通过此类加载配置类创建Spring容器,它用于读取类上的注解配置
### 3. `getBean()`方法
* ApplicationContext提供了多种getBean方法的重载,常用的如下:
| 方法 | 参数 | 返回值 |
| --------------------------------------- | --------------- | ------------------ |
| `getBean(String beanId)` | bean的id | `Object`,bean对象 |
| `getBean(String beanId,Class beanType)` | bean的Class类型 | bean对象 |
| `getBean(Class beanType)` | | bean对象 |
19.练习
写一个curd的功能,要使用Spring的IoC的方式进行解耦
* 建表语句:account.sql
* 项目需要导入的jar包依赖:
mysql驱动, 连接池,JdbcTemplate(QueryRunner),spring,单元测试
* 在dao层,需要有一个JdbcTemplate对象:dao层有一个依赖需要注入
* 配置service对象,依赖一个dao对象:注入dao对象
* 配置dao对象,依赖一个JdbcTemplate对象:注入JdbcTemplate对象
* 配置JdbcTemplate对象,依赖一个连接池对象:注入连接池对象
* 配置连接池对象,依赖于四个简单值:驱动类名、地址、用户名、密码,注入简单值
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
pom.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>com.itheima</groupId>
<artifactId>day37_spring2_curd_xml</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
resource 路径下:
jdbc.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring1
jdbc.username=root
jdbc.password=root
applicationContext-dao.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">
<!--AccountDao-->
<bean id="accountDao" class="com.zengjx.dao.impl.AccountDaoImpl">
<property name="runner" ref="runner"/>
</bean>
<!--QueryRunner-->
<bean id="runner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource"/>
</bean>
<!--连接池-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns: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">
<!--引入外部的properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--使用import引入模块的配置文件-->
<import resource="classpath:applicationContext-dao.xml"/>
<!--AccountService-->
<bean id="accountService" class="com.zengjx.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
</beans>
dao层:
package com.zengjx.dao;
import com.zengjx.domain.Account;
import java.sql.SQLException;
import java.util.List;
public interface AccountDao {
List<Account> queryAll() throws SQLException;
Account findById(Integer id) throws SQLException;
void save(Account account) throws SQLException;
void edit(Account account) throws SQLException;
void delete(Integer id) throws SQLException;
}
package com.zengjx.dao.impl;
import com.zengjx.dao.AccountDao;
import com.zengjx.domain.Account;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
public class AccountDaoImpl implements AccountDao {
private QueryRunner runner;
public void setRunner(QueryRunner runner) {
this.runner = runner;
}
@Override
public List<Account> queryAll() throws SQLException {
return runner.query("select * from account", new BeanListHandler<>(Account.class));
}
@Override
public Account findById(Integer id) throws SQLException {
return runner.query("select * from account where id = ?", new BeanHandler<>(Account.class), id);
}
@Override
public void save(Account account) throws SQLException {
runner.update("insert into account (id,name,money) values(?,?,?)", account.getId(), account.getName(), account.getMoney());
}
@Override
public void edit(Account account) throws SQLException {
runner.update("update account set name = ?, money = ? where id = ?", account.getName(), account.getMoney(), account.getId());
}
@Override
public void delete(Integer id) throws SQLException {
runner.update("delete from account where id = ?", id);
}
}
domain:映射数据库
package com.zengjx.domain;
public class Account {
private Integer id;
private String name;
private Float money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getMoney() {
return money;
}
public void setMoney(Float money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
service:
package com.zengjx.service;
import com.zengjx.domain.Account;
import java.sql.SQLException;
import java.util.List;
public interface AccountService {
List<Account> queryAll() throws SQLException;
Account findById(Integer id) throws SQLException;
void save(Account account) throws SQLException;
void edit(Account account) throws SQLException;
void delete(Integer id) throws SQLException;
}
package com.zengjx.service.impl;
import com.zengjx.dao.AccountDao;
import com.zengjx.domain.Account;
import com.zengjx.service.AccountService;
import java.sql.SQLException;
import java.util.List;
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public List<Account> queryAll() throws SQLException {
return accountDao.queryAll();
}
@Override
public Account findById(Integer id) throws SQLException {
return accountDao.findById(id);
}
@Override
public void save(Account account) throws SQLException {
accountDao.save(account);
}
@Override
public void edit(Account account) throws SQLException {
accountDao.edit(account);
}
@Override
public void delete(Integer id) throws SQLException {
accountDao.delete(id);
}
}
package com.zengjx.test;
import com.zengjx.domain.Account;
import com.zengjx.service.AccountService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.sql.SQLException;
import java.util.List;
public class SpringCurdTest {
private AccountService accountService;
@Test
public void testQueryAll() throws SQLException {
List<Account> accounts = accountService.queryAll();
for (Account account : accounts) {
System.out.println(account);
}
}
@Test
public void testFindById() throws SQLException {
Account account = accountService.findById(4);
System.out.println(account);
}
@Test
public void testSave() throws SQLException {
Account account = new Account();
account.setName("rose");
account.setMoney(100f);
accountService.save(account);
}
@Test
public void testEdit() throws SQLException {
Account account = accountService.findById(4);
account.setMoney(0f);
accountService.edit(account);
}
@Test
public void testDelete() throws SQLException {
accountService.delete(4);
}
@Before
public void init(){
ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
accountService = app.getBean("accountService", AccountService.class);
}
}
测试结果:
-
表示层Spring MVC
-
持久层Spring JDBCTemplate
-
业务层事务管理等
-
耦合性:程序之间的依赖性。
-
编译期依赖:编译时必须提供依赖的类,否则编译不通过。应当避免编译期依赖
-
运行期依赖:运行时必须提供依赖的类,否则不能运行
-
-
耦合性越强,维护成本就越高
-
开发时要求:高内聚,低耦合
-
来源:CSDN
作者:Rsingstarzengjx
链接:https://blog.csdn.net/oDianZi1234567/article/details/104113647