目录
博主所使用的软件版本为
idea 2017
jdk版本 1.8.0
maven版本 3.5.4
Spring框架开发程序的方式
编写service和dao的类,持久层选择使用原始的JDBC的程序,连接池选择的是Druid连接池,演示代码,来理解Spring框架开发程序的方式。
创建maven工程,导入开发的jar包
java
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
创建数据库,创建表结构
java
create database spring_db;
use spring_db;
create table account(
id int primary key auto_increment,
name varchar(40),
money double
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',3000);
insert into account(name,money) values('bbb',3000);
insert into account(name,money) values('ccc',1000);
insert into account(name,money) values('熊大',1000);
insert into account(name,money) values('熊二',500);
insert into account(name,money) values('大大怪将军',5000);
insert into account(name,money) values('小小怪下士',3000);
insert into account(name,money) values('小心',1000);
insert into account(name,money) values('花',1000);
编写JavaBean的类
类中的属性要和数据库表中的属性相对应
java
public class Account {
private Integer id;
private String name;
private Double 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 Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
编写AccountDao的接口和实现类
AccountDao接口
java
public interface AccountDao {
public List<Account> findAll();
}
AccountDaoImpl实现类
java
public class AccountDaoImpl implements AccountDao {
// 注入连接池对象
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 查询所有的数据
* @return
*/
@Override
public List<Account> findAll() {
/*
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
*/
List<Account> list = new ArrayList<>();
Connection connection = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
// 获取连接
connection = dataSource.getConnection();
// 编写sql语句
String sql = "select * from account";
// 预编译
stmt = connection.prepareStatement(sql);
// 查询
rs = stmt.executeQuery();
// 遍历,封装数据
while (rs.next()){
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
list.add(account);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
}
创建业务层AccountService接口和其AccountServiceImpl 实现类
AccountService接口
java
public interface AccountService {
public List<Account> findAll();
}
AccountServiceImpl 实现类
java
public class AccountServiceImpl implements AccountService {
// 依赖注入
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
/**
* 查询所有的数据
* @return
*/
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
}
编写测试文件applicationConfig.xml
java
<?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="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///spring_db" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!--管理bean-->
<bean id="accountService" class="cn.tx.service.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>
<bean id="accountDao" class="cn.tx.dao.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
编写测试类
java
public class Demo1 {
@Test
public void run1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService accountService = (AccountService) ac.getBean("accountService");
// 调用方法
List<Account> list = accountService.findAll();
for (Account account : list) {
System.out.println(account);
}
}
}
测试结果:
IOC注解的方式
IOC注解方式的快速入门(半注解)
IOC注解的方式依赖没有变化
半注解的方式省去了在配置文件中配置<bean>并手写被Spring管理的类及其属性和属性值
编写接口和实现类
java
package com.qcby.demo2;
/*
* 业务层接口
* 用户模块接口
* 目的:演示springIOC入门
*/
public interface UserService {
//接口中的抽象方法
public void hello();
}
在需要管理的类上添加@Component注解表示这个类交给Spring去管理
@Component(value = "us")相当于配置文件中<bean id="us" class="com.qcby.demo2.UserServiceImpl" />
java
package com.qcby.demo2;
/*
* 用户模块实现类实现用户模块接口
* 实现其抽象方法
* 耦合度低
* */
import com.qcby.demo2.UserService;
// 组件,作用:把当前类使用IOC容器进行管理,如果没有指定名称,默认使用类名,首字母是小写。userServiceImpl。或者自己指定名称
@Component(value = "us")
public class UserServiceImpl implements UserService{
//实现入门
@Override
public void hello() {
System.out.println("Hello IOC!!");
}
编写配置文件,重点是开启注解扫描。半注解一定要开启扫描。
扫描指定位置的包其下的类
java
<?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="com.qcby.demo2" />
-->
<!--开启注解扫描 com.qcby.所有的包中的所有的类 -->
<context:component-scan base-package="com.qcby" />
</beans>
编写测试方法
java
public class Demo2 {
/**
* IOC注解方式的入门
*/
@Test
public void run1(){
// 工厂
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_anno.xml");
// 获取对象
UserService userService = (UserService) ac.getBean("us");
userService.hello();
}
}
IOC常用的注解
bean管理类常用的4个注解(作用相同,推荐使用在不同分层上)
@Component 普通的类
@Controller 表现层
@Service 业务层
@Repository 持久层
依赖注入常用的注解
@Value 用于注入普通类型(String,int,double等类型)
@Autowired 默认按类型进行自动装配(引用类型)
@Qualifier 和@Autowired一起使用,强制使用名称注入
@Resource Java提供的注解,也被支持。使用name属性,按名称注入对象生命周期(作用范围)注解
@Scope 生命周期注解,取值singleton(默认值,单实例)和prototype(多例)
初始化方法和销毁方法注解(了解)
@PostConstruct 相当于init-method
@PreDestroy 相当于destroy-method
注解的一些具体实现
创建Car类
java
package com.qcby.demo3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
// 默认当前类名就是ID名称,首字母小写
@Component(value = "c")
// @Controller
// @Service(value = "c")
// @Repository(value = "c")
// @Scope(value = "singleton") // 默认值,单例的
// @Scope(value = "prototype") // 多例的
public class Car {
// 注解注入值,属性set方法是可以省略不写的。
// 只有一个属性,属性的名称是value,value是可以省略不写的
@Value("大奔2")
private String cname;
@Value(value = "400000")
private Double money;
// 也不用提供set方法
// 按类型自动装配的注解,和id名称没有关系
@Autowired
// 按id的名称注入,Qualifier不能单独使用,需要Autowired一起使用。
// @Qualifier(value = "person")
// @Resource Java提供的注解,按名称注入对象,属性名称是name
// @Resource(name = "person")
private Person person;
/**
* Car对象创建完成后,调用init方法进行初始化操作
*/
@PostConstruct
public void init(){
System.out.println("操作...");
}
/*
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
*/
@Override
public String toString() {
return "Car{" +
"cname='" + cname + '\'' +
", money=" + money +
", person=" + person +
'}';
}
}
创建Person类
java
package com.qcby.demo3;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value = "person")
public class Person {
@Value("张三")
private String pname;
@Override
public String toString() {
return "Person{" +
"pname='" + pname + '\'' +
'}';
}
}
在配置文件中开启扫描
java
<?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.tx.demo2" />
-->
<!--开启注解扫描 cn.tx.所有的包中的所有的类 -->
<context:component-scan base-package="com.qcby"/>
</beans>
创建测试类
java
package com.qcby.demo;
import com.qcby.demo3.Car;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo3 {
@Test
public void run1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) ac.getBean("c");
System.out.println(car);
}
}
测试结果:
IOC纯注解的方式
IOC纯注解方式
省略了在配置文件,不需要开启扫描,使用配置类来代替配置文件
纯注解的目的是替换掉所有的配置文件。但是需要编写配置类。
编写实体类
java
package com.qcby.demo4;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Order {
@Value("北京")
private String address;
@Override
public String toString() {
return "Order{" +
"address='" + address + '\'' +
'}';
}
}
编写配置类,替换掉applicationContext.xml配置文件
java
package com.qcby.demo4;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* Spring的配置类,替换掉applicationContext.xml
*
*/
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcby.demo4")
public class SpringConfig {
}
测试方法的编写
java
package com.qcby.demo;
import com.qcby.demo4.OrderServiceImpl;
import com.qcby.demo4.SpringConfig1;
import com.qcby.demo401.Order01;
import com.qcby.demo4.Order;
import com.qcby.demo4.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo4 {
/**
* 编写程序,需要加载配置类
*/
@Test
public void run1(){
// 创建工厂,加载配置类
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
// 获取到对象
Order order = (Order) ac.getBean("order");
System.out.println(order);
}
}
常用的注解总结
@Configuration 声明是配置类
@ComponentScan 扫描具体包结构的
@Import注解 Spring的配置文件可以分成多个配置的,编写多个配置类。用于导入其他配置类
@Bean注解 只能写在方法上,表明使用此方法创建一个对象,对象创建完成保存到IOC容器中
java
package com.qcby.demo4;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.sql.DataSource;
/**
* 新的配置类
*/
@Configuration //声明配置类
public class SpringConfig1 {
@Bean("dataSource")
public DataSource createDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///demotest");
dataSource.setUsername("root");
dataSource.setPassword("2020");
return dataSource;
}
}
java
// 声明当前类是配置类
@Configuration
// 扫描指定的包结构
@ComponentScan(value = "com.qcby.demo4")
// @ComponentScan(value = {"com.qcby.demo4","com.qcby.demo3"})
// 引入新的配置类
@Import(value = {SpringConfig1.class})
public class SpringConfig {
Spring框架整合JUnit单元测试
每次进行单元测试的时候,都需要编写创建工厂,加载配置文件等代码,比较繁琐。Spring提供了整合Junit单元测试的技术,可以简化测试开发。
必须先有Junit单元测试的环境,也就是说已经导入Junit单元测试的jar包。咱们已经导入过了。使用的是4.12版本
再导入spring-test的坐标依赖
java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
编写类和方法
java
package com.qcby.demo6;
import org.springframework.stereotype.Component;
@Component
public class Customer {
public void save(){
System.out.println("保存客户");
}
}
编写配置类
java
package com.qcby.demo6;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//声明当前类是配置类
@Configuration
//扫描包结构
@ComponentScan(value = "com.qcby.demo6")
public class SpringConfig6 {
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)为固定写法
java
package com.qcby.demo;
import com.qcby.demo6.Customer;
import com.qcby.demo6.SpringConfig6;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) // 运行单元测试
加载类路径下的配置文件
@ContextConfiguration(classes = SpringConfig6.class)
public class Demo6 {
// 测试哪一个对象,把该对象注入进来,在测试环境下,可以使用注解的方式注入测试的对象
// 按类型自动注入
@Autowired
private Customer customer;
@Test
public void run1(){
// 创建工厂,加载配置文件......
// 调用对象的方法
customer.save();
}
}