今天内容
- Spring框架的AOP之注解的方式
- Spring框架的JDBC模板
- Spring框架的事务管理
案例一:使用Spring框架的AOP技术对DAO层的功能进行增强
- 使用Spring框架的AOP技术对DAO层的功能进行增强
技术分析之:Spring框架的AOP技术(注解方式)
1, 步骤一:创建JavaWEB项目(本例名称为day37_aop
),引入具体的开发的jar包
先引入Spring框架开发的基本开发包
再引入Spring框架的AOP的开发包
spring的传统AOP的开发的包
spring-aop-4.2.4.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
aspectJ的开发包
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar
2, 步骤二:创建Spring的配置文件,引入具体的AOP的schema约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
3, 步骤三:创建包结构,编写具体的接口和实现类
- com.itheima.demo1
- CustomerDao -- 接口
- CustomerDaoImpl -- 实现类
4, 步骤四:将目标类配置到Spring中
<bean id="customerDao" class="com.itheima.demo1.CustomerDaoImpl"/>
5, 步骤五:定义切面类
① 添加切面和通知的注解
@Aspect -- 定义切面类的注解
通知类型(注解的参数是切入点的表达式)
@Before -- 前置通知
@AfterReturing -- 后置通知
@Around -- 环绕通知
@After -- 最终通知
@AfterThrowing -- 异常抛出通知
② 具体的代码如下
@Aspect
public class MyAspectAnno {
@Before(value="execution(public void com.itheima.demo1.CustomerDaoImpl.save())")
public void log(){
System.out.println("记录日志...");
}
}
6, 步骤六:在配置文件中定义切面类
<bean id="myAspectAnno" class="com.itheima.demo1.MyAspectAnno"/>
7, 步骤七:在配置文件中开启自动代理
<aop:aspectj-autoproxy/>
8, 完成测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
@Resource(name="customerDao")
private CustomerDao customerDao;
@Test
public void run1(){
customerDao.save();
customerDao.update();
}
}
例:使用注解完成AspectJ的AOP开发
1, 新建JavaWEB项目(本例名称为day37_aop
)
2, 导入jar包,参考上面步骤,本例导入所有jar包如下:
com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.apache.commons.logging-1.1.1.jar com.springsource.org.apache.log4j-1.2.15.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar spring-aop-4.2.4.RELEASE.jar spring-aspects-4.2.4.RELEASE.jar spring-beans-4.2.4.RELEASE.jar spring-context-4.2.4.RELEASE.jar spring-core-4.2.4.RELEASE.jar spring-expression-4.2.4.RELEASE.jar spring-test-4.2.4.RELEASE.jar
3, 在src目录下引入log4j.properties,参考spring以前笔记
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
4,类和接口如下:
package com.huachao.demo1;
public interface CustomerDao {
public void save();
public void update();
}
public class CustomerDaoImp implements CustomerDao {
@Override
public void save() {
System.out.println("客户 保存...");
}
@Override
public void update() {
System.out.println("客户 更新...");
}
}
5,使用注解的切面类
package com.huachao.demo1;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyAspectJAnnotation {
@Before(value="execution(* com.huachao.demo1.CustomerDaoImp.save(..))")
public void log()
{
System.out.println("记录日志...");
}
}
6,在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"
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">
<bean id="customerDao" class="com.huachao.demo1.CustomerDaoImp"/>
<bean id="myAspectJAnnotation" class="com.huachao.demo1.MyAspectJAnnotation"/>
<aop:aspectj-autoproxy/>
</beans>
7,测试类如下:
package com.huachao.demo1;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo1 {
@Resource(name="customerDao")
public CustomerDao customerDao;
@Test
public void Run1()
{
customerDao.save();
customerDao.update();
}
}
技术分析之通知类型
- 通知类型
- @Before -- 前置通知
- @AfterReturing -- 后置通知
- @Around -- 环绕通知(目标对象方法默认不执行的,需要手动执行)
- @After -- 最终通知
- @AfterThrowing -- 异常抛出通知
- 配置通用的切入点
- 使用@Pointcut定义通用的切入点
@Aspect
public class MyAspectAnno {
@Before(value="MyAspectAnno.fn()")
public void log(){
System.out.println("记录日志...");
}
@Pointcut(value="execution(public void com.itheima.demo1.CustomerDaoImpl.save())")
public void fn(){}
}
例:通知类型
package com.huachao.demo1;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspectJAnnotation {
/*
* 通知类型:@Before前置通知(切入点表达式)
*/
//@Before(value="execution(* com.huachao.demo1.CustomerDaoImp.save(..))")
/*
* 引入自定义切入点
*/
@Before(value="MyAspectJAnnotation.fn()")
public void log()
{
System.out.println("记录日志...");
}
/**
* 最终通知:方法执行成功或者出现异常,都会执行
*/
//@After(value="execution(* com.huachao.demo1.CustomerDaoImp.save(..))")
/*
* 引入自定义切入点
*/
@After(value="MyAspectJAnnotation.fn()")
public void after()
{
System.out.println("记录日志...");
}
/**
* 自定义切入点
* 必须依赖方法,但是这个方法名随意
*/
@Pointcut(value="execution(* com.huachao.demo1.CustomerDaoImp.save(..))")
public void fn(){}
/**
* 环绕通知(目标对象方法默认不执行的,需要手动执行)
* @param joinPoint
*/
@Around(value="MyAspectJAnnotation.fn()")
public void around(ProceedingJoinPoint joinPoint)
{
System.out.println("环绕前...");
try {
joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕后...");
}
}
案例二:Spring框架的事务管理完成转账的案例
需求分析
- 完成一个转账的功能,需要进行事务的管理,使用Spring的事务管理的方式完成
Spring框架的JDBC模板技术
技术分析之Spring框架的JDBC模板技术概述
- Spring框架中提供了很多持久层的模板类来简化编程,使用模板类编写程序会变的简单
- 提供了JDBC模板,Spring框架提供的
JdbcTemplate类
- Spring框架可以整合Hibernate框架,也提供了模板类
HibernateTemplate类
技术分析之演示JDBC的模板类
1, 步骤一:创建数据库的表结构
create database spring_day03;
use spring_day03;
create table t_account(
id int primary key auto_increment,
name varchar(20),
money double
);
2, 引入开发的jar包
先引入IOC基本的6个jar包
com.springsource.org.apache.commons.logging-1.1.1.jar com.springsource.org.apache.log4j-1.2.15.jar spring-beans-4.2.4.RELEASE.jar spring-context-4.2.4.RELEASE.jar spring-core-4.2.4.RELEASE.jar spring-expression-4.2.4.RELEASE.jar
再引入Spring-aop的jar包
spring-aop-4.2.4.RELEASE.jar
最后引入JDBC模板需要的jar包
MySQL数据库的驱动包
本例使用mysql:mysql-connector-java-5.1.7-bin.jar
Spring-jdbc.jar
spring-jdbc-4.2.4.RELEASE.jar
Spring-tx.jar
spring-tx-4.2.4.RELEASE.jar
3,引入applicationContext.xml
和log4j.properties
配置文件
4, 编写测试代码(自己来new对象的方式)
@Test
public void Run1()
{
// Spring框架提供了内置的连接池,不想使用内置,可以整合其他的连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring_day03");
dataSource.setUsername("root");
dataSource.setPassword("root");
//创建模板类
JdbcTemplate template = new JdbcTemplate();
//设置连接池
template.setDataSource(dataSource);
//完成操作
template.update("insert into t_account values (null,?,?)","冠希",1000);
}
技术分析之使用Spring框架来管理模板类
1, 刚才编写的代码使用的是new的方式,应该把这些类交给Spring框架来管理。
2, 修改的步骤如下
- 步骤一:Spring管理内置的连接池
<!-- 配置Spring提供的连接池 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///spring_day03"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
- 步骤二:Spring管理模板类
<!-- 配置JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
- 步骤三:编写测试程序
package com.huachao.demo1;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo2 {
@Resource(name="jdbcTemplate")
private JdbcTemplate template;
@Test
public void Run1()
{
template.update("insert into t_account values (null,?,?)","冠希2",1000);
}
}
技术分析之Spring框架管理开源的连接池
1, 管理DBCP连接池
先引入DBCP的2个jar包,在
day35_Spring01\资料\spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.dbcp\1.2.2.osgi
和day35_Spring01\资料\spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.pool\1.5.3
目录下com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
编写配置文件
<!-- 配置DBCP连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///spring_day03"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
2, 管理C3P0连接池
先引入C3P0的jar包,在
day35_Spring01\资料\spring-framework-3.0.2.RELEASE-dependencies\com.mchange.c3p0\com.springsource.com.mchange.v2.c3p0\0.9.1.2
目录下com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
编写配置文件
<!-- 配置C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
技术分析之Spring框架的JDBC模板的简单操作
- 增删改查的操作
package com.huachao.demo1;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo2 {
@Resource(name="jdbcTemplate")
private JdbcTemplate template;
/**
* 插入
*/
@Test
public void Run1()
{
template.update("insert into t_account values (null,?,?)","冠希4",1000);
}
/**
* 修改
*/
@Test
public void Run2()
{
template.update("update t_account set name=? where id=?","美美",3);
}
/**
* 删除
*/
@Test
public void Run3()
{
template.update("delete from t_account where id=?",4);
}
/**
* 查询一条数据
*/
@Test
public void Run4()
{
Account ac = template.queryForObject("select * from t_account where id=?", new BeanMapper(), 1);
System.out.println(ac.toString());
}
/**
* 查询所有数据
*/
@Test
public void Run5()
{
List<Account> list = template.query("select * from t_account", new BeanMapper());
System.out.println(list);
}
class BeanMapper implements RowMapper<Account>{
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
}
}
技术分析之Spring框架的事务管理
技术分析之事务的回顾
- 事务:指的是逻辑上一组操作,组成这个事务的各个执行单元,要么一起成功,要么一起失败!
- 事务的特性
- 原子性
- 一致性
- 隔离性
- 持久性
- 如果不考虑隔离性,引发安全性问题
读问题:
① 脏读:
② 不可重复读:
③ 虚读:写问题:
① 丢失更新:
- 如何解决安全性问题
- 读问题解决,设置数据库隔离级别
- 写问题解决可以使用 悲观锁和乐观锁的方式解决