Spring第二天笔记
一、内容介绍
1、使用IOC完成CRUD
2、基于注解的IOC配置
3、使用注解改造CRUD(半xml半注解)
4、纯注解开发
5、spring与junit的整合
二、使用IOC完成改造CRUD
a、引入依赖
<!--spring的核心包(基本)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--dbutils-->
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.4</version>
</dependency>
<!--c3p0数据源-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
b、持久层
1 接口
public interface AccountDao {
public List<Account> findAll();
public Account findById(Integer id);
public void save(Account account);
public void update(Account account);
public void del(Integer id);
}
2. 实现类
public class AccountDaoImpl implements AccountDao {
QueryRunner queryRunner;
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
@Override
public List<Account> findAll() {
String sql = "select * from account";
try {
List<Account> accountList = queryRunner.query(sql, new BeanListHandler<Account>(Account.class));
return accountList;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public Account findById(Integer id) {
String sql = "select * from account where id = ?";
try {
Account account = queryRunner.query(sql, new BeanHandler<>(Account.class), id);
return account;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public void save(Account account) {
String sql = "insert into account values(null , ? , ?)";
try {
queryRunner.update(sql ,account.getName() ,account.getMoney());
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void update(Account account) {
String sql = "update account set name = ? ,money = ? where id = ?";
try {
queryRunner.update(sql ,account.getName(),account.getMoney(),account.getId());
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void del(Integer id) {
String sql = "delete from account where id = ?";
try {
queryRunner.update(sql ,id);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
c、业务层
1. 接口
public interface AccountService {
public List<Account> findAll();
public Account findById(Integer id);
public void save(Account account);
public void update(Account account);
public void del(Integer id);
}
2. 实现类
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
@Override
public Account findById(Integer id) {
return accountDao.findById(id);
}
@Override
public void save(Account account) {
accountDao.save(account);
}
@Override
public void update(Account account) {
accountDao.update(account);
}
@Override
public void del(Integer id) {
accountDao.del(id);
}
}
d、配置文件(重点)
<?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">
<!--在测试时需要用到Service对象,创建service对象-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao" ></property>
</bean>
<!--在AccountService中需要AccountDao对象-->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<property name="queryRunner" ref="queryRunner"></property>
</bean>
<!--在AccountDao中需要QueryRunner对象,创建对象-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<!--按照类型在构造方法注入数据源对象-->
<constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
</bean>
<!--在QueryRunner对象中需要DataSource对象-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!--通过set方法注入必要的四个属性-->
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
f、测试类
public class TestCRUD {
@Test
public void testFindAll(){
//创建容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//创建service对象
AccountService accountService = ac.getBean("accountService",AccountService.class);
List<Account> accountList = accountService.findAll();
for (Account account : accountList) {
System.out.println(account);
}
}
}
三、常用的注解
a. 注解开发入门流程
1.引入依赖
<!--引入spring的核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
2. 配置文件:applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--
开启注解,指定扫描的包 : context:component-scan
引入context名称空间-引入约束
base-package:指定要扫描的包, 扫描的是包及其子包
-->
<context:component-scan base-package="com.itheima"></context:component-scan>
</beans>
在需要创建对象的类上添加注解
@Component
public class UserDaoImpl implements UserDao {
@Override
public void print() {
System.out.println("Dao实现类执行");
}
}
测试
//创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取对象
UserDao userDao = ac.getBean(UserDao.class);
System.out.println(userDao);
UserService userService = ac.getBean(UserService.class);
System.out.println(userService);
b. @Component – 标记在类上,不能用在方法上
作用:创建对象, 只要标记了,扫描了该包,对象就会创建
衍生了三个子注解
@Controller 一般用于web(控制层)
@Service 一般用于业务层
@Repository 一般用于持久层
相当于xml
<bean id="" class="全限类名"></bean>
@Component("userDao")属性:value="userDao" 相当于xml的 id="userDao"
如果没有指定value属性,默认的名称是 简单类名,首字母小写
UserDaoImpl -- userDaoImpl
UserServiceImpl -- userServiceImpl
c. @Autowired – 自动注入
可以标记在属性和set方法上,如果标记在属性上,可以没有set方法
特点:默认自动按照类型注入
流程:当属性|set方法标记了@Autowired ,会自动在容器中查询该属性类型的对象,
如果有且只有一个,则注入
@Qualifier :必须与@Autowired结合使用
作用:如果自动注入按照类型注入失败,则按照指定的名称注入
如果没有@Qualifier,类型注入失败,则按照属性名按照名称注入
@Resource -- 自动注入
流程:当属性|set方法标记了@Resource,会自动按照名称注入, 如果名称没有找到,
则根据类型注入,如果类型有多个,则抛出异常
@Autowired : 默认按照类型注入,如果类型有多个,则按照名称注入 -- spring提供的
@Resource : 默认按照名称注入,没有名称没有找到,按照类型注入 -- jdk提供的
d、一些注解与xml的映射关系
@Configuration : 标记该类为配置文件类
可以替换 applicationContext.xml
@ComponentSacn("com.itheima")
相当于:<context:component-scan base-package="com.itheima">
@Import: 引入其他配置文件类
<import resource="classpath:applicationContext-dao.xml"></import>
@Bean -- 通过方法创建对象,一般用于创建别人提供的类
相当于:<bean >标签创建类对象
@Scope("singleton|prototype")(单例或多例)
配置对象的范围:相当于:bean标签中的属性 scope="singleton|prototype"
生命周期
@PostConstruct:相当于bean标签的属性 init-method,指定初始化方法
@PreDestroy:相当于bean标签的属性:destroy-method, 指定对象的销毁方法
@Value 给属性赋值 -- 只能赋值简单类型(复杂类型只能@Autowired )
@PropertySource : 引入外部属性文件
相当于:<context:property-placeholder location="classpath:jdbc.properties">
</context:property-placeholder>
四、使用注解改造账户CRUD(半注解半配置)
持久层
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
@Autowired
QueryRunner queryRunner;
public List<Account> findAll() {
String sql = "select * from account";
try {
List<Account> accountList = queryRunner.query(sql, new BeanListHandler<Account>(Account.class));
return accountList;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
业务层
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
}
d、配置文件
<?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.itheima"></context:component-scan>
<!--创建queryRunner对象, 需要数据源对象,创建数据源对象,通过构造方法注入-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<!--通过构造方法参数类型注入-->
<constructor-arg type="javax.sql.DataSource" ref="dataSource"></constructor-arg>
</bean>
<!--创建数据源对象:需要注入四个参数-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--通过set方法注入-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
e、测试
/**
* 1. 替换Junit的运行器: 为spring与junit整合后的运行器
* 2. 指定配置文件路径, 会自动创建容器对象
* @ContextConfiguration({"classpath:applicationContext.xml"})
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:applicationContext.xml"})
public class TestCRUD {
// ApplicationContext ac;
// @Before
// public void init(){
// //创建容器
// ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// }
@Autowired
AccountService accountService;
@Test
public void testFindAll(){
//创建service对象
List<Account> accountList = accountService.findAll();
for (Account account : accountList) {
System.out.println(account);
}
}
}
五、纯注解开发
- SpringConfiguration.java
/**
* 1. 标记该类为配置文件类 @Configuration
* 2. 指定注解扫描的包路径 @ComponentScan({"com.itheima"})
* 3. 引入其他配置文件类 @Import({JDBCConfiguration.class})
*/
@Configuration
@ComponentScan({"com.itheima"})
@Import({JDBCConfiguration.class})
public class SpringConfiguration {
}
- JDBCConfiguration.java
/**
* 配置持久层的对象
* @Configuration :这里可以省略的
*
* @Bean("name") 用在方法上,用来指定方法创建的对象存到容器中
* "name": 就是在容器的名称
*/
@Configuration
public class JDBCConfiguration {
@Bean("queryRunner")
public QueryRunner createQueryRunner(DataSource dataSource){
// 需用通过构造方法注入dataSource
QueryRunner queryRunner = new QueryRunner(dataSource);
return queryRunner;
}
/**
* 创建数据源对象:dataSource
*/
@Bean("dataSource")
public DataSource createDataSource(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUser("root");
dataSource.setPassword("root");
try {
dataSource.setDriverClass("com.mysql.jdbc.Driver");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return dataSource;
}
}
- 测试
//纯注解创建容器对象
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
//创建service对象
AccountService accountService = ac.getBean("accountService",AccountService.class);
六、spring与junit的整合
- 引入依赖
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--引入spring-5 的测试包: 必须引用相应的junit包, junit的版本必须是4.12以上-->
<!--引入spring-4 的测试包: 必须引用相应的junit包, junit的版本必须是4.9以上-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
2.1 配置测试环境-- xml
a. 替换Junit的运行器: 为spring与junit整合后的运行器
@RunWith(SpringJUnit4ClassRunner.class)
b. 指定配置文件路径, 会自动创建容器对象, 必须添加classpath
@ContextConfiguration({"classpath:applicationContext.xml"})
2.2 配置测试环境-- ann
a. 替换Junit的运行器: 为spring与junit整合后的运行器
@RunWith(SpringJUnit4ClassRunner.class)
b. 指定配置文件路径, 会自动创建容器对象, 必须添加classpath
@ContextConfiguration(classes = {SpringConfiguration.class})
3. 测试:从容器可以获取某类型的对象
@Autowired
AccountService accountService;
整合后的运用在四中的测试里有体现。