Spring框架
今日内容
- 能够编写spring的IOC的注解代码
- 能够编写spring使用注解实现组件扫描
- 能够说出spring的IOC的相关注解的含义
- 能够实现spring框架整合JUnit
DBCP连接池的使用
由Apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开。DataSource接口实现类BasicDataSource。
//创建DataSource接口实现类对象
BasicDataSource dataSource = new BasicDataSource();
//设置数据库驱动类
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//设置连接URL
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
//设置连接用户名和密码
dataSource.setUsername("root");
dataSource.setPassword("root");
DBUtils实现账户表增删改查
private QueryRunner qr ;
@Before
public void before(){
BasicDataSource dataSource = new BasicDataSource();
//设置数据库驱动类
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//设置连接URL
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
//设置连接用户名和密码
dataSource.setUsername("root");
dataSource.setPassword("root");
qr = new QueryRunner(dataSource);
}
/**
* DBUtils查询全部
*/
@Test
public void testQueryByList()throws SQLException{
String sql = "select * from account";
List<Account> list = qr.query(sql, new BeanListHandler<Account>(Account.class));
if(list != null && list.size() > 0 ){
for(Account account : list){
System.out.println(account);
}
}
}
/**
* DBUtils主键查询
*/
@Test
public void testQueryById() throws SQLException {
String sql = "select * from account where id = ?";
Account account = qr.query(sql, new BeanHandler<Account>(Account.class), 3);
System.out.println(account);
}
/**
* DBUtils删除数据
*/
@Test
public void testDelete()throws SQLException{
String sql = "delete from account where id = ?";
int row = qr.update(sql, 4);
System.out.println("影响行数:"+row);
}
/**
* DBUtils更新数据
*/
@Test
public void testUpdate()throws SQLException{
String sql = "update account set name = ? , money = ? where id = ?";
int row = qr.update(sql, "赵六哥哥",100.33,4);
System.out.println("影响行数:"+row);
}
/**
* DBUtils新增数据
*/
@Test
public void testInsert() throws SQLException {
String sql = "insert into account(name,money) values (?,?)";
int row = qr.update(sql,"赵六",99);
System.out.println("操作影响行数:"+row);
}
Account表的CRUD(SpringIOC实现)
实现思想
-
maven工程引入坐标
- junit
- mysql驱动
- dbcp数据库连接池
- dbutils数据库工具
- dao层service层涉及到很多对象的管理(Spring-context)
-
开发步骤分析
- 引入坐标(如上)
- Account表的pojo开发
- 开发dao层代码(dao接口和实现类)
- 在dao实现类当中使用dbutils操作数据库
- sevice层开发
- 上述过程中涉及到的对象和对象之间的引用注入交给Spring管理
-
applicationContext.xml配置
<!-- 配置dbcp连接池--> <bean id="basicDataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <!-- BasicDataSource成员注入--> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 配置QueryRunner--> <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner"> <!-- 构造方法注入--> <constructor-arg name="ds" ref="basicDataSource"></constructor-arg> </bean> <!-- 配置业务层--> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <!-- 业务层set方法,注入--> <property name="accountDao" ref="accountDao"></property> </bean> <!-- 配置持久层--> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <!-- 持久层queryRunner注入--> <property name="qr" ref="queryRunner"></property> </bean>
-
AccountDaoImpl
private QueryRunner qr; public void setQr(QueryRunner qr) { this.qr = qr; } @Override public void saveAccount(Account account) throws SQLException { String sql = "insert into account values(?,?,?)"; qr.update(sql,null,account.getName(),account.getMoney()); }
-
AccountServiceImpl
private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void saveAccount(Account account) { try { accountDao.saveAccount(account); } catch (SQLException e) { e.printStackTrace(); } }
-
测试程序
@Test public void testSaveAccount(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); AccountService service = applicationContext.getBean("accountService", AccountService.class); Account account = new Account(); account.setName("小名"); account.setMoney(200.32); service.saveAccount(account); }
Spring注解开发
bean标签和注解的对应
- 添加applicationContext配置文件命名空间
<?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"
>
<!-- 开启spring的注解扫描,扫描包中类的注解-->
<context:component-scan base-package="com.itheima"></context:component-scan>
</beans>
-
bean标签对应注解@Component
- 注解属性value:bean标签的id属性
- 不指定value属性,默认就是类名,首字母小写
- 该注解衍生出了三个注解,@Controller,@Service,@Repository,用法和@Componet一致,为了更加清晰的提现层的概念。
-
bean标签属性scope对应注解@Scope
- 注解属性value:singleton,prototype
-
bean标签属性init-method对应注解@PostConstruct
-
bean标签属性destroy-method对应注解@PreDestroy
-
service层
@Component("accountService") @Service("accountService") @Scope("prototype") public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void saveAccount(Account account) { accountDao.saveAccount(account); } }
-
dao层
//@Component("accountDao") public class AccountDaoImpl implements AccountDao { @Override public void saveAccount(Account account) { System.out.println("模拟转账"); } }
-
测试注解
@Test public void testIOC(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); AccountService accountService = context.getBean("accountService", AccountService.class); AccountDao accountDao = context.getBean("accountDao",AccountDao.class); System.out.println(accountService); System.out.println(accountDao); context.close(); }
依赖注入注解
-
@Autowired注解(Spring框架提供)
按照类型注入,如果无法确定唯一类型(接口有多个实现类),需要配合疏解@Qualifier的使用,@Qualifier(“id”)。
注解注入,不要setXXX方法。
-
业务层
@Service("accountService") @Scope("singleton") public class AccountServiceImpl implements AccountService { @Autowired @Qualifier("accountDao") private AccountDao accountDao; @Override public void saveAccount(Account account) { accountDao.saveAccount(account); } }
-
@Resource注解(JDK提供)
- 注解属性name:配置类的id
@Resource(name="accountDao") private AccountDao accountDao;
半注解半xml改造(CRUD)
企业开发的主流
注意:往往第三方jar中的对象我们使用xml配置(比如dbcp数据库连接池、dbutils的QueryRunner),类似于service层和dao层的实现类,这属于我们自己写的代码,往往会使用注解,这就是半xml半注解的模式。
-
applicationContext.xml配置
<?xml version="1.0" encoding="UTF-8"?> <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 "> <!-- 开启Spring的注解扫描--> <context:component-scan base-package="com.itheima"></context:component-scan> <!-- 配置dbcp连接池--> <bean id="basicDataSource" class="org.apache.commons.dbcp2.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 配置QueryRunner对象--> <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner"> <constructor-arg ref="basicDataSource"></constructor-arg> </bean> </beans>
-
dao层
@Repository("accountDao") public class AccountDaoImpl implements AccountDao { @Autowired @Qualifier("queryRunner") private QueryRunner qr; @Override public void saveAccount(Account account) throws SQLException { String sql = "insert into account values(?,?,?)"; qr.update(sql,null,account.getName(),account.getMoney()); } }
-
service层
@Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired @Qualifier("accountDao") private AccountDao accountDao; @Override public void saveAccount(Account account) { try { accountDao.saveAccount(account); } catch (SQLException e) { e.printStackTrace(); } } }
-
测试
@Test public void testSaveAccount(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); AccountService service = context.getBean("accountService", AccountService.class); Account account = new Account(); account.setName("testName"); account.setMoney(0.99); service.saveAccount(account); }
纯注解开发(CRUD)
-
@Configuration标识当前类是Spring的一个配置类
-
@ComponentScan替代xml中的
<context:component-scan/>
-
@Import引入其他配置类,被引入的配置类可以不加@Configuration注解
-
@PropertySource:引入外部properties文件,注意加classpath:
-
@Value对成员变量赋值
-
@Bean将一个方法的返回值对象加入到Spring的容器当中管理
-
@Qualifier可以使用在方法上,表明对应的形参引入/注入的对象类型
-
SpringConfig框架启动配置类
//Spring配置类,框架启动入口 @Configuration //启动注解扫描 @ComponentScan({"com.itheima"}) public class SpringConfig { //方法的返回值,加入到SpringIOC容器中管理 @Bean("basicDataSource") public DataSource createDataSource(){ BasicDataSource basicDataSource = new BasicDataSource(); basicDataSource.setDriverClassName("com.mysql.jdbc.Driver"); basicDataSource.setUrl("jdbc:mysql://localhost:3306/test"); basicDataSource.setUsername("root"); basicDataSource.setPassword("root"); return basicDataSource; } //方法的返回值,加入到SpringIOC容器中管理 @Bean("queryRunner") //@Qualifier("basicDataSource"),对参数进行注入 public QueryRunner createQueryRunner( @Qualifier("basicDataSource") DataSource ds){ QueryRunner queryRunner = new QueryRunner(ds); return queryRunner; } }
-
dao层
@Repository("accountDao") public class AccountDaoImpl implements AccountDao { @Autowired @Qualifier("queryRunner") private QueryRunner qr; @Override public void saveAccount(Account account) throws SQLException { String sql = "insert into account values(?,?,?)"; qr.update(sql,null,account.getName(),account.getMoney()); } }
-
service层
@Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired @Qualifier("accountDao") private AccountDao accountDao; @Override public void saveAccount(Account account) { try { accountDao.saveAccount(account); } catch (SQLException e) { e.printStackTrace(); } } }
-
测试
@Test public void testAnnotation() { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); AccountService service = context.getBean("accountService", AccountService.class); Account account = new Account(); account.setName("testAnnoName"); account.setMoney(1.98); service.saveAccount(account); }
注解开发的SpringConfig配置优化
-
SpringConfig框架启动配置类
//Spring配置类,框架启动入口 @Configuration //启动注解扫描 @ComponentScan({"com.itheima"}) //引入JDBC的配置类 @Import({JDBCConfig.class}) public class SpringConfig { }
-
JDBCConfig配置类
@Configuration @PropertySource("classpath:jdbc.properties") public class JDBCConfig { //注入配置文件中的键值对 @Value("${jdbc.driver}") private String driverClassName; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; //方法的返回值,加入到SpringIOC容器中管理 @Bean("basicDataSource") public DataSource createDataSource(){ BasicDataSource basicDataSource = new BasicDataSource(); basicDataSource.setDriverClassName(driverClassName); basicDataSource.setUrl(url); basicDataSource.setUsername(username); basicDataSource.setPassword(password); return basicDataSource; } //方法的返回值,加入到SpringIOC容器中管理 @Bean("queryRunner") //@Qualifier("basicDataSource"),对参数进行注入 public QueryRunner createQueryRunner(@Qualifier("basicDataSource") DataSource ds){ QueryRunner queryRunner = new QueryRunner(ds); return queryRunner; } }
Spring对Junit的支持
- junit运行的时候底层使用了Runner对象,有一个默认使用的Runner对象。
- Spring对junit的支持,其实是自己实现了一个Runner对象(按照junit runner的要求实现)
- Spring对junit的支持的体现
- 好处一:配置完之后,不需要我们手动的启动Spring,而是会很方便的启动Spring
- 好处二:可以在junit测试类中使用@AutoWired等方式注入对象,直接对其进行调用测试
- 使用步骤
- 引入jar
- 配置你的测试类
//Spring框架中的Runner对象,替换Junit中的runner对象
@RunWith(SpringJUnit4ClassRunner.class)
//框架启动入口,配置类启动
@ContextConfiguration(classes = SpringConfig.class)
//框架启动入口,xml配置文件启动
//@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class MainTest
{
//注入业务层接口
@Autowired
@Qualifier("accountService")
private AccountService service;
@Test
public void testAnnotation() {
Account account = new Account();
account.setName("testAnnoName3");
account.setMoney(3.98);
service.saveAccount(account);
}
}