在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候, 让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件, 创建和获取三层对象的类就是工厂
实例
properties配置文件
accountService=com.itfzk.service.impl.AccouontServiceImpl
accountDao=com.itfzk.dao.impl.AccountDaoImpl
Bean 对象的工厂模式类
public class BeanFuctory {
//定义一个 Properties 对象
private static Properties properties;
//定义一个 Map,用于存放我们创建的对象,我们称之为容器
private static Map<String, Object> beans;
//使用静态代码块对 Properties 对象赋值
static {
try {
//实例化对象
properties = new Properties();
//获取 Properties 的流对象
InputStream inputStream = BeanFuctory.class.getClassLoader().getResourceAsStream("bean.properties");
properties.load(inputStream);
//实例化容器对象
beans = new HashMap<String, Object>();
//取出配置文件中所有的 key
Enumeration<Object> keys = properties.keys();
//遍历枚举
while (keys.hasMoreElements()){
//取出每个 key
String key = keys.nextElement().toString();
//通过 key 获取 value
String beanPath = properties.getProperty(key);
//利用反射机制实例化对象
Object value = Class.forName(beanPath).newInstance();
//将 key 和 value 存储在 Map 中
beans.put(key, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 根据 Bean 的名称获取 bean 对象
* @param beanName
* @return
*/
public static Object getBean(String beanName){
return beans.get(beanName);
}
}
第一步:导入必备的 jar 包到工程中
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.0.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.hamcrestgroupId>
<artifactId>hamcrest-coreartifactId>
<version>1.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.27version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.6version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>2.1_3version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
dependencies>
第二步:在 resources 路径下创建一个任意名称的 xml 文件 ,并给配置文件导入约束
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
beans>
第三步: 在刚创建的 xml 文件中,配置 spring 管理资源,在配置文件中配置 service 和 dao
<bean id="accountService" class="cn.itfzk.spring.service.impl.AccouontServiceImpl">bean>
<bean id="accountDao" class="cn.itfzk.spring.dao.impl.AccountDaoImpl">bean>
第四步:测试配置是否成功
/**
* 获取 Spring 的 IOC 核心容器,并根据 id 获取对象
*
* ApplicationContext 三种常用实现类
* ClassPathXmlApplicationContext :加载类路径下的配置文件,要求配置文件必须在类路径下,不在的话,加载不了(更常用)
* FileSystemXmlApplicationContext :加载磁盘任意路径下的配置文件(必须有访问权限)
* AnnotationConfigApplicationContext :读取注解创建容器
* @param args
*/
public static void main(String[] args) {
//获取核心容器对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//根据 id 获取 Bean 对象
IAccountService as = (IAccountService) applicationContext.getBean("accountService");
IAccountDao ad = (IAccountDao) applicationContext.getBean("accountDao");
System.out.println(as);
System.out.println(ad);
}
作用:
属性:
配置 bean 标签的属性(xml配置文件)
<bean id="accountService" class="cn.itfzk.spring02.service.impl.AccouontServiceImpl"
scope="singleton" init-method="init" destroy-method="destroy">bean>
单例对象: scope=“singleton”
一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:
init-method: 指定类中的初始化方法名称
destroy-method: 指定类中销毁方法名称
对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
多例对象: scope=“prototype”
每次访问对象时,都会重新创建对象实例。
生命周期:
init-method: 指定类中的初始化方法名称
destroy-method: 指定类中销毁方法名称
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了
第一种方式:使用默认构造函数创建
在 Spring 的配置文件中使用 Bean 对象,配以 id 和 class 属性之后,且没有其他属性和标签时,采用的就是默认构造函数创建 Bean 对象,此时如果类中没有默认构造函数,则对象无法创建。
<bean id="accountService" class="cn.itfzk.spring01.service.impl.AccouontServiceImpl">bean>
第二种方式:使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入 Spring 容器)
服务层实现类
public class AccouontServiceImpl {
public AccouontServiceImpl(String str){
System.out.println("创建 AccouontServiceImpl 对象");
}
public void saveAccount() {
System.out.println("service 中的 saceAccount 方法执行力。。。");
}
}
模拟一个工厂类(将这个类看成是 jar 包中的类)
public class InstanceFactory {
public IAccountService getAccountService(){
return new AccouontServiceImpl("naem");
}
}
xml配置文件
<bean id="instanceFactory" class="cn.itfzk.spring01.factory.InstanceFactory" >bean>
<bean id="accountService" factory-bean="instanceFactory"
factory-method="getAccountService" >bean>
第三种方法:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入 Spring 容器)
服务层实现类
public class AccouontServiceImpl {
public AccouontServiceImpl(String str){
System.out.println("创建 AccouontServiceImpl 对象");
}
public void saveAccount() {
System.out.println("service 中的 saceAccount 方法执行力。。。");
}
}
模拟一个工厂类(将这个类看成是 jar 包中的类)
public class StaticFactory {
//静态方法
public static IAccountService getAccountService(){
return new AccouontServiceImpl("naem");
}
}
xml配置文件
<bean id="accountService" class="cn.itfzk.spring01.factory.StaticFactory"
factory-method="getAccountService">bean>
使用的标签:constructor-arg
标签的位置:bean 标签的内部
标签的属性:
name:用于指定给构造函数中指定名称的参数赋值(常用的)
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置从 0 开始
以上三个用于指定给构造函数中哪个参数赋值
value:用于提供基本类型和 String 类型的数据
ref:用于指定其他的 bean 类型数据,它指的就是在 Spring 的 IOC 核心容器中出现过的 bean
对象优势:在获取 Bean 对象时,注入数据是必须的操作,否则对象无法创建成功
弊端:改变了 bean 对象的实例化方式,使我们在创建对象时,如果用不上这些数据,也必须提供
//构造函数注入类
public class AccouontServiceImpl {
private String name;
private int age;
private Date birthday;
public AccouontServiceImpl(String name, int age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
}
<bean id="accountService" class="cn.itfzk.spring03.service.impl.AccouontServiceImpl" >
<constructor-arg name="name" value="fzk" >constructor-arg>
<constructor-arg name="age" value="20">constructor-arg>
<constructor-arg name="birthday" ref="now" >constructor-arg>
bean>
<bean id="now" class="java.util.Date" >bean>
//set方法的注入类
public class AccouontServiceImpl01 {
private String name;
private int age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
<bean id="accountService01" class="cn.itfzk.spring03.service.impl.AccouontServiceImpl01" >
<property name="name" value="fzk" >property>
<property name="age" value="20" >property>
<property name="birthday" ref="now" >property>
bean>
<bean id="now" class="java.util.Date" >bean>
//复杂类型的注入/集合类型的注入
public class AccouontServiceImpl02 implements IAccountService {
private Object[] myStrs;
private List<Object> myList;
private Set<Object> mySet;
private Map<Object, Object> myMap;
private Properties myPros;
public void setMyStrs(Object[] myStrs) {
this.myStrs = myStrs;
}
public void setMyList(List<Object> myList) {
this.myList = myList;
}
public void setMySet(Set<Object> mySet) {
this.mySet = mySet;
}
public void setMyMap(Map<Object, Object> myMap) {
this.myMap = myMap;
}
public void setMyPros(Properties myPros) {
this.myPros = myPros;
}
}
<bean id="accountService02" class="cn.itfzk.spring03.service.impl.AccouontServiceImpl02" >
<property name="myStrs" >
<array>
<value>fffvalue>
<value>zzzvalue>
array>
property>
<property name="myList" >
<list>
<value>fffvalue>
<value>zzzvalue>
list>
property>
<property name="mySet" >
<set>
<value>fffvalue>
<value>zzzvalue>
set>
property>
<property name="myMap" >
<map>
<entry key="fff" value="fff">entry>
<entry key="zzz" value="zzz">entry>
map>
property>
<property name="myPros" >
<props>
<prop key="fff">fffprop>
<prop key="zzz">zzzprop>
props>
property>
bean>
步骤
创建数据库
CREATE TABLE `caogao` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
Javabean类
public class Account implements Serializable {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
业务层接口及业务层实现类
/**
* 业务层接口
*/
public interface IAccountService {
//查询所有
public List<Account> findAll();
//根据 id 查询信息
public Account findById(int id);
//保存信息
public void save(Account account);
//修改信息
public void update(Account account);
//删除信息
public void delete(int id);
}
/**
* 业务层实现类
*/
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
//查询所有
public List<Account> findAll() {
return accountDao.findAll();
}
//根据 id 查询信息
public Account findById(int id) {
return accountDao.findById(id);
}
//保存信息
public void save(Account account) {
accountDao.save(account);
}
//保存信息
public void update(Account account) {
accountDao.update(account);
}
//删除信息
public void delete(int id) {
accountDao.delete(id);
}
}
持久层接口及持久层实现类
/**
* 持久层接口
*/
public interface IAccountDao {
//查询所有
public List<Account> findAll();
//根据 id 查询信息
public Account findById(int id);
//保存信息
public void save(Account account);
//修改信息
public void update(Account account);
//删除信息
public void delete(int id);
}
/**
* 持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
private QueryRunner queryRunner;
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
//查询所有
public List<Account> findAll() {
List<Account> accounts = null;
try {
String sql = "select * from caogao";
accounts = queryRunner.query(sql, new BeanListHandler<Account>(Account.class));
} catch (SQLException e) {
e.printStackTrace();
}
return accounts;
}
//按照id查询
public Account findById(int id) {
Account account = null;
try {
String sql = "select * from caogao where id=?";
account = queryRunner.query(sql, new BeanHandler<Account>(Account.class), id);
} catch (SQLException e) {
e.printStackTrace();
}
return account;
}
//保存信息
public void save(Account account) {
try {
String sql = "insert into caogao(username, password) values(?,?)";
queryRunner.update(sql, account.getUsername(), account.getPassword());
} catch (SQLException e) {
e.printStackTrace();
}
}
//修改信息
public void update(Account account) {
try {
String sql = "update caogao set username=?, password=? where id=?";
queryRunner.update(sql, account.getUsername(), account.getPassword(), account.getId());
} catch (SQLException e) {
e.printStackTrace();
}
}
//删除信息
public void delete(int id) {
try {
String sql = "delete from caogao where id=?";
queryRunner.update(sql, id);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
xml 配置文件
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountService" class="net.memory.Spring01.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao">property>
bean>
<bean id="accountDao" class="net.memory.Spring01.dao.impl.AccountDaoImpl">
<property name="queryRunner" ref="queryRunner">property>
bean>
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource">constructor-arg>
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver">property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/fzk">property>
<property name="user" value="root">property>
<property name="password" value="123456">property>
bean>
beans>
测试类
public class accountTest {
private ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testBean.xml");
private IAccountService accountService = (IAccountService) applicationContext.getBean("accountService");
//查询所有测试
@Test
public void findAllTest(){
List<Account> accounts = accountService.findAll();
for(Account account : accounts){
System.out.println(account);
}
}
//按照id查询测试
@Test
public void findByIdTest(){
Account account = accountService.findById(2);
System.out.println(account);
}
//保存信息测试
@Test
public void saveTest(){
Account account = new Account();
account.setUsername("123");
account.setPassword("123");
accountService.save(account);
}
//修改信息测试
@Test
public void update(){
Account account = new Account(8, "psq", "123");
accountService.update(account);
}
//删除信息测试
@Test
public void deleteTest(){
accountService.delete(8);
}
}
第一步:导入必备的 jar 包到工程中
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.0.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.hamcrestgroupId>
<artifactId>hamcrest-coreartifactId>
<version>1.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.27version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.6version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>2.1_3version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
dependencies>
第二步:使用@Component 注解配置管理的资源
@Component("accountService")
public class AccountServiceImpl implements IAccountService {
private IAccountDao accountDao;
public void setAccountDao(IAccountDao accountDao) {
this.accountDao = accountDao;
}
}
第三步: 创建 spring 的 xml 配置文件并开启对注解的支持
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="net.memory">context:component-scan>
beans>
第四步:测试配置是否成功
public class Client {
public static void main(String[] args) {
ApplicationContext application = new ClassPathXmlApplicationContext("testBean.xml");
IAccountService accountService = (IAccountService) application.getBean("accountService");
System.out.println(accountService);
}
}
相当于xml:
@Autowired
作用:自动按照类型注入,只要容器中有唯一的一个 Bean 对象类型和要注入的变量类型匹配,就注入成功如果 IOC 容器中没有任何 Bean 类型和要注入的变量类型匹配则报错
@Qualifier
作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用,但是在给方法参数注入时可以
@Resource
作用:直接按照 bean 的 id 注入,可以单独使用
以上三个注解都只能注入其他 bean 类型的数据,而基本类型和 String 类型无法使用,另外,集合类型的注入只能通过 XML 来实现
@Value()
作用:用于注入基本类型和 String 类型
注解的优势:
XML 的优势:
Spring 管理 Bean 方式的比较:
基于XML配置 | 基于注解配置 | |
---|---|---|
Bean定义 | @Component 衍生类@Repository @Service @Controller |
|
Bean名称 | 通过id或name指定 | @Component("**") |
Bean注入 | 或 |
@Autowired 按类型注入 @Qualifer 按名称注入 @Resource 按bean的id注入 @Value 注入基本类型和 String 类型 |
生命过程、Bean作用范围 | init-method destroy-method 范围scope属性 |
@PostConstruct初始化 @PreDestroy 销毀 @Scope设置作用范围 |
适合场景 | Bean来自第三方,使用其它 | Bean的实现类由用户自己开发 |
@Configuration
//该类是一个 spring 配置类
@Configuration
public class Config {
}
@ComponentScan
//扫描指定的包:cn.itfzk.spring05
@Configuration
@ComponentScan(basePackages = {"cn.itfzk.spring05"})
public class Config {
}
@Bean
public class JdbcConfig {
/**
* 创建 QueryRunner 对象
* @param dataSource
* @return
* @Bean(name = "runner") 和 createQueryRunner 方法相当于:
*
*
*
*/
@Bean(name = "queryRunner")
public QueryRunner createQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
/**
* 创建 DataSource 对象
* @return
* @Bean(name = "dataSource") 和 createDataSource 方法相当于:
*
*
*
*
*
*
*/
@Bean(name = "dataSource")
public DataSource createDataSource(){
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/fzk");
ds.setUser("root");
ds.setPassword("123456");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return ds;
}
}
@Import
@Configuration
@Import(value = {JdbcConfig.class}) //用于导入其他配置的类
public class Config {
}
@PropertySource
//properties 文件中的配置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/fzk
jdbc.name=root
jdbc.password=123456
@Configuration
@PropertySource(value = {"classpath:jdbc.properties"}) //加载 properties 文件中的配置
public class Config {
@Value("${jdbc.driver}") //取出 properties 文件中的 jdbc.driver 数据
private String driver;
}
通过注解获取容器
ApplicationContext application = new AnnotationConfigApplicationContext(SpringConfiguration.class);
第一步:导入必备的 jar 包到工程中
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.0.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.hamcrestgroupId>
<artifactId>hamcrest-coreartifactId>
<version>1.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.27version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.6version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>2.1_3version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
dependencies>
第二步:使用@RunWith 注解替换原有运行器
@RunWith(SpringJUnit4ClassRunner.class) //替换原有运行器
public class accountTest {
}
第三步:使用@ContextConfiguration 指定 spring 配置文件的位置
xml 方法来指定 spring 配置文件的位置
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:testBean.xml") //指定 spring 配置文件的位置
public class accountTest {
注解 方法来指定 spring 配置文件的位置
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class) //指定 spring 配置文件的位置
public class accountTest {
第四步:使用@Autowired 给测试类中的变量注入数据
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
@ContextConfiguration(locations = "classpath:testBean.xml")
public class accountTest {
@Autowired //给测试类中的变量注入数据
private IAccountService accountService;
}
业务层(接口,类)
//业务层接口
public interface IAccountService {
//查询所有
List<Account> findAll();
//按 id 查询
Account findById(int id);
//按 username 查询
Account findByName(String username);
//添加信息
void saveAccount(Account account);
//修改信息
void updateAccount(Account account);
//按 id 删除信息
void deleteById(int id);
//交换信息
void changeMessage(String username1, String username2);
}
//业务层实现类
public class AccountServiceImpl implements IAccountService {
private AccountDaoImpl accountDao;
public void setAccountDao(AccountDaoImpl accountDao) {
this.accountDao = accountDao;
}
//查询所有信息
public List<Account> findAll() {
return accountDao.findAll();
}
//按 id 查询信息
public Account findById(int id) {
return accountDao.findById(id);
}
//按 username 查询信息
public Account findByName(String username) {
return accountDao.findByName(username);
}
//添加信息
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
//修改信息=
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
//删除信息=
public void deleteById(int id) {
accountDao.deleteById(id);
}
//交换信息,将 username1 和 username2 的名字交换=
public void changeMessage(String username1, String username2) {
accountDao.changeMessage(username1, username2);
}
}
//持久层接口
public interface IAccountDao {
//查询所有
List<Account> findAll();
//按 id 查询
Account findById(int id);
//按 username 查询
Account findByName(String username);
//添加信息
void saveAccount(Account account);
//修改信息
void updateAccount(Account account);
//按 id 删除信息
void deleteById(int id);
//交换信息
void changeMessage(String username1, String username2);
}
//持久层实现类
public class AccountDaoImpl implements IAccountService {
private QueryRunner queryRunner;
private ConnectionUtils connectionUtils;
public void setConnectionUtils(ConnectionUtils connectionUtils) {
this.connectionUtils = connectionUtils;
}
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
//查询所有信息
public List<Account> findAll() {
try {
return queryRunner.query(connectionUtils.getThreadConnection() ,"select * from caogao", new BeanListHandler<Account>(Account.class));
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//按 id 查询信息
public Account findById(int id) {
try {
return queryRunner.query(connectionUtils.getThreadConnection() ,"select * from caogao where id=?", new BeanHandler<Account>(Account.class), id);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//按 username 查询信息
public Account findByName(String username) {
try {
return queryRunner.query(connectionUtils.getThreadConnection() ,"select * from caogao where username=?", new BeanHandler<Account>(Account.class), username);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//添加信息
public void saveAccount(Account account) {
try {
queryRunner.update(connectionUtils.getThreadConnection() ,"insert into caogao(username, password) values(?,?)", account.getUsername(), account.getPassword());
} catch (SQLException e) {
e.printStackTrace();
}
}
//修改信息
public void updateAccount(Account account) {
try {
queryRunner.update(connectionUtils.getThreadConnection() ,"update caogao set username=?, password=? where id=?", account.getUsername(), account.getPassword(), account.getId());
} catch (SQLException e) {
e.printStackTrace();
}
}
//删除信息
public void deleteById(int id) {
try {
queryRunner.update(connectionUtils.getThreadConnection() ,"delete from caogao where id=?", id);
} catch (SQLException e) {
e.printStackTrace();
}
}
//交换信息,将 username1 和 username2 的信息交换
public void changeMessage(String username1, String username2) {
//1、查询 username1 的信息
Account user1 = findByName(username1);
//2、查询 username2 的信息
Account user2 = findByName(username2);
//3、修改 username1 的信息
user1.setUsername(username2);
//4、修改 username2 的信息
user2.setUsername(username1);
//5、更新 username1 的信息
updateAccount(user1);
//模拟网络错误
int i = 10 / 0;
//6、更新 username2 的信息
updateAccount(user2);
}
}
连接的工具类
public class ConnectionUtils {
private ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
//获取连接
public Connection getThreadConnection(){
//从 ThreadLocal 获取连接
Connection connection = threadLocal.get();
//判断是否有连接
if(connection == null){
try {
//从数据源中获取一个连接,并存入 ThreadLocal 中
connection = dataSource.getConnection();
threadLocal.set(connection);
} catch (SQLException e) {
e.printStackTrace();
}
}
return connection;
}
//把连接和线程解绑
public void removeConnection(){
threadLocal.remove();
}
}
事务相关的工具类
public class TransactionManager {
private ConnectionUtils connectionUtils;
public void setConnectionUtils(ConnectionUtils connectionUtils) {
this.connectionUtils = connectionUtils;
}
/**
* 开启事务
*/
public void beginTransation(){
try {
connectionUtils.getThreadConnection().setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 提交事务
*/
public void commit(){
try {
connectionUtils.getThreadConnection().commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 回滚事务
*/
public void rollback(){
try {
connectionUtils.getThreadConnection().rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 释放事务
*/
public void close(){
try {
connectionUtils.getThreadConnection().close(); //还回线程池
connectionUtils.removeConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
AccountServiceImpl 的代理工厂类
public class BeanFactory {
private IAccountService accountService;
private TransactionManager transactionManager;
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public void setAccountService(IAccountService accountService) {
this.accountService = accountService;
}
public IAccountService getAccountService() {
return (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(),
accountService.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke;
try {
//1、开启事务
transactionManager.beginTransation();
//2、执行操作
invoke = method.invoke(accountService, args);
//3、提交事务
transactionManager.commit();
//4、返回结果
return invoke;
}catch (Exception e){
//5、回滚事务
transactionManager.rollback();
throw new RuntimeException(e);
}finally{
//6、释放连接
transactionManager.close();
}
}
});
}
}
xml 配置文件
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="accountService" class="itfzk.project.service.impl.AccountServiceImpl" >
<property name="accountDao" ref="accountDao" >property>
bean>
<bean id="accountDao" class="itfzk.project.dao.impl.AccountDaoImpl" >
<property name="queryRunner" ref="queryRunner" >property>
<property name="connectionUtils" ref="connectionUtils" >property>
bean>
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype" >
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="driverClass" value="com.mysql.jdbc.Driver" >property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/fzk" >property>
<property name="user" value="root" >property>
<property name="password" value="123456" >property>
bean>
<bean id="connectionUtils" class="itfzk.project.utils.ConnectionUtils" >
<property name="dataSource" ref="dataSource" >property>
bean>
<bean id="transactionManager" class="itfzk.project.utils.TransactionManager" >
<property name="connectionUtils" ref="connectionUtils" >property>
bean>
<bean id="beanFactory" class="itfzk.project.factory.BeanFactory" >
<property name="accountService" ref="accountService" >property>
<property name="transactionManager" ref="transactionManager" >property>
bean>
<bean id="accountDaoImpl_BeanFactory" factory-bean="beanFactory" factory-method="getAccountService" >bean>
beans>
第一步:导入必备的 jar 包到工程中
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.0.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.hamcrestgroupId>
<artifactId>hamcrest-coreartifactId>
<version>1.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.27version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.6version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>2.1_3version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
dependencies>
第二步:创建 spring 的配置文件并导入约束
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
beans>
第三步:把通知类用 bean 标签配置起来
<bean id="txManager" class="cn.itfzk.spring07.log.Logger">bean>
第四步:使用 aop:config 声明 aop 配置
<aop:config>
aop:config>
第五步:使用 aop:aspect 配置切面
<aop:config>
<aop:aspect id="txAdvice" ref="txManager">
aop:aspect>
aop:config>
第六步:使用 aop:pointcut 配置切入点表达式
<aop:aspect id="txAdvice" ref="txManager">
<aop:pointcut id="pt1" expression="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())"/>
aop:aspect>
第七步:使用 aop:xxx 配置对应的通知类型
<aop:pointcut id="pt1" expression="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())"/>
<aop:before method="beforeLog" pointcut-ref="pt1">aop:before>
<aop:after-returning method="afterReturningLog" pointcut-ref="pt1">aop:after-returning>
<aop:after-throwing method="afterThrowingLog" pointcut-ref="pt1">aop:after-throwing>
<aop:after method="afterLog" pointcut-ref="pt1">aop:after>
作用: 用于声明开始 aop 的配置
<aop:config>
aop:config>
作用:
属性:
<aop:config>
<aop:aspect id="txAdvice" ref="txManager">
aop:aspect>
aop:config>
aop:before :配置前置通知
aop:after-returning :配置后置通知
aop:after-throwing :配置异常通知
aop:after :配置最终通知
以上四个标签的属性:
method 属性:用于指定前置通知类的方法
pointcut 属性:用于指定切入点的表达式
pointcut 属性切入点表达式的写法:
关键字:execution
标准写法:
全通配写法(* 代表任意):
* *..*.*(..)
不使用 aop:pointcut
<aop:before method="beforeLog" pointcut="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())">aop:before>
<aop:after-returning method="afterReturningLog" pointcut="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())">aop:after-returning>
<aop:after-throwing method="afterThrowingLog" pointcut="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())">aop:after-throwing>
<aop:after method="afterLog" pointcut="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())">aop:after>
<aop:pointcut id="pt1" expression="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())"/>
<aop:before method="beforeLog" pointcut-ref="pt1">aop:before>
<aop:after-returning method="afterReturningLog" pointcut-ref="pt1">aop:after-returning>
<aop:after-throwing method="afterThrowingLog" pointcut-ref="pt1">aop:after-throwing>
<aop:after method="afterLog" pointcut-ref="pt1">aop:after>
作用:
属性:
说明:
注意:
<aop:config>
<aop:aspect id="txAdvice" ref="transactionManaget">
<aop:pointcut id="pt" expression="execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))"/>
<aop:around method="aroundAccount" pointcut-ref="pt">aop:around>
aop:aspect>
aop:config>
//环绕通知实现方法
public Object aroundAccount(ProceedingJoinPoint proceedingJoinPoint){
Object proceed = null;
try {
//前置通知
beginTransaction();
Object[] args = proceedingJoinPoint.getArgs();
proceed = proceedingJoinPoint.proceed();
//后置通知
commit();
} catch (Throwable throwable) {
//异常通知
rollback();
throwable.printStackTrace();
} finally {
//最终通知
close();
}
return proceed;
}
作用:
属性:
<aop:pointcut id="pt1" expression="execution(* cn.itfzk.spring07.service.impl.AccountServiceImpl.save())"/>
第一步:导入必备的 jar 包到工程中
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.0.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.hamcrestgroupId>
<artifactId>hamcrest-coreartifactId>
<version>1.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.27version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.6version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>2.1_3version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
dependencies>
第二步:创建 spring 的配置文件并导入约束
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
beans>
第三步:把资源使用注解配置
@Service("accountService")
public class AccountServiceImpl implements IAccountService {
}
第四步:在配置文件中指定 spring 要扫描的包
<context:component-scan base-package="net.memory">context:component-scan>
第五步:把通知类也使用注解配置 @Component
@Component("transactionManager") //使用注解配置
public class TransactionManager {
}
第六步:在通知类上使用 @Aspect 注解声明为切面
@Component("transactionManager")
@Aspect //使用@Aspect 注解声明为切面
public class TransactionManager {
}
第七步:在增强的方法上使用注解配置通知
@Before、@AfterReturning、@AfterThrowing、@After(前置、后置、异常、最终通知)
@Component("transactionManaget")
@Aspect
public class TransactionManaget {
@Autowired
private ConnectionUtils connectionUtils;
//前置通知
@Before("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
public void beginTransaction(){
try {
connectionUtils.getConnection().setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
//后置通知
@AfterReturning("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
public void commit(){
try {
connectionUtils.getConnection().commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
//异常通知
@AfterThrowing("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
public void rollback(){
try {
connectionUtils.getConnection().rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
//最终通知
@After("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
public void close(){
try {
connectionUtils.getConnection().close();
} catch (SQLException e) {
e.printStackTrace();
}
connectionUtils.removeConnection();
}
}
@Around(环绕通知)
@Component("transactionManaget")
@Aspect
public class TransactionManaget {
@Autowired
private ConnectionUtils connectionUtils;
//前置通知
public void beginTransaction(){
try {
connectionUtils.getConnection().setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
//后置通知
public void commit(){
try {
connectionUtils.getConnection().commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
//异常通知
public void rollback(){
try {
connectionUtils.getConnection().rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
//最终通知
public void close(){
try {
connectionUtils.getConnection().close();
} catch (SQLException e) {
e.printStackTrace();
}
connectionUtils.removeConnection();
}
//环绕通知
@Around("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
public Object aroundAccount(ProceedingJoinPoint proceedingJoinPoint){
Object proceed = null;
try {
beginTransaction(); //前置通知
Object[] args = proceedingJoinPoint.getArgs();
proceed = proceedingJoinPoint.proceed();
commit(); //后置通知
} catch (Throwable throwable) {
rollback(); //异常通知
throwable.printStackTrace();
} finally {
close(); //最终通知
}
return proceed;
}
}
第八步:在 spring 配置文件中开启 spring 对注解 AOP 的支持
<context:component-scan base-package="net.memory">context:component-scan>
<aop:aspectj-autoproxy />
作用:
@Component("transactionManager")
@Aspect //使用@Aspect 注解声明为切面
public class TransactionManager {
}
@Before :把当前方法看成是前置通知。
@AfterReturning :把当前方法看成是后置通知。
@AfterThrowing :把当前方法看成是异常通知。
@After :把当前方法看成是最终通知
@Before("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
@AfterReturning("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
@AfterThrowing("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
@After("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
作用:
@Around("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
作用:指定切入点表达式
属性:
@Pointcut("execution(* net.memory.Spring01.service.impl.AccountServiceImpl.*(..))")
public void pt1(){
}
@Before("pt1()")
@AfterReturning("pt1()")
@AfterThrowing("pt1()")
@After("pt1()")
@Around("pt1()")
@Configuration
@ComponentScan(basePackages = {"net.memory"}) //扫描指定的包:cn.itfzk.spring05
@Import(JdbcConfiguration.class)
@EnableAspectJAutoProxy //开启 spring 对注解 AOP 的支持
public class SpringConfiguration {
}
xml 配置文件
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql://localhost:3306/fzk">property>
<property name="username" value="root">property>
<property name="password" value="123456">property>
bean>
beans>
JdbcTemplate使用类
public class JdbcTemplateDemo {
private ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean08.xml");
private JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
/**
* 查询所有
*/
@Test
public void findAll(){
String sql = "select * from caogao";
List<Account> accounts = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class));
for(Account account : accounts){
System.out.println(account);
}
}
/**
* 获取其他类型的数据
*/
@Test
public void find(){
String sql = "select count(*) from caogao";
Long fzk = jdbcTemplate.queryForObject(sql, Long.class);
System.out.println(fzk);
}
/**
* 按条件查询
*/
@Test
public void findById(){
String sql = "select * from caogao where id = ?";
List<Account> accounts = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class), 2);
System.out.println(accounts.get(0));
}
/**
* 修改
*/
@Test
public void updateById(){
String sql = "update caogao set username = ?, password = ? where id = ?";
jdbcTemplate.update(sql, "fff123", "fff123", 2);
}
/**
* 添加信息
*/
@Test
public void add(){
String sql = "insert into caogao(username, password) values(?,?)";
jdbcTemplate.update(sql, "psq", "123");
}
/**
* 删除信息
*/
@Test
public void delete(){
String sql = "delete from caogao where id = ?";
jdbcTemplate.update(sql, 7);
}
}
xml 配置文件
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="jdbcTemplateDemo" class="cn.itfzk.spring08.JdbcTemplateDemo">
<property name="jdbcTemplate" ref="jdbcTemplate">property>
bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql://localhost:3306/fzk">property>
<property name="username" value="root">property>
<property name="password" value="123456">property>
bean>
beans>
JdbcTemplate使用类
public class JdbcTemplateDemo {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 查询所有
*/
public List<Account> findAll(){
String sql = "select * from caogao";
List<Account> accounts = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class));
return accounts;
}
/**
* 获取其他类型的数据
*/
public Integer find(){
String sql = "select count(*) from caogao";
Integer fzk = jdbcTemplate.queryForObject(sql, Long.class);
return fzk;
}
/**
* 按条件查询
*/
public Account findById(){
String sql = "select * from caogao where id = ?";
List<Account> accounts = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class), 2);
return accounts.get(0);
}
/**
* 修改
*/
public void updateById(){
String sql = "update caogao set username = ?, password = ? where id = ?";
jdbcTemplate.update(sql, "fff123", "fff123", 2);
}
/**
* 添加信息
*/
public void add(){
String sql = "insert into caogao(username, password) values(?,?)";
jdbcTemplate.update(sql, "psq", "123");
}
/**
* 删除信息
*/
public void delete(){
String sql = "delete from caogao where id = ?";
jdbcTemplate.update(sql, 7);
}
}
xml 配置问价
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="jdbcTemplateDemo" class="cn.itfzk.spring08.JdbcTemplateDemo">
<property name="dataSource" ref="dataSource">property>
bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver">property>
<property name="url" value="jdbc:mysql://localhost:3306/fzk">property>
<property name="username" value="root">property>
<property name="password" value="123456">property>
bean>
beans>
继承JdbcDaoSupport类
public class JdbcTemplateDemo extends JdbcDaoSupport {
/**
* 查询所有
*/
public List<Account> findAll(){
String sql = "select * from caogao";
List<Account> accounts = getJdbcTemplate().query(sql, new BeanPropertyRowMapper<Account>(Account.class));
return accounts;
}
/**
* 获取其他类型的数据
*/
public Integer find(){
String sql = "select count(*) from caogao";
Integer fzk = getJdbcTemplate().queryForObject(sql, Long.class);
return fzk;
}
/**
* 按条件查询
*/
public Account findById(){
String sql = "select * from caogao where id = ?";
List<Account> accounts = getJdbcTemplate().query(sql, new BeanPropertyRowMapper<Account>(Account.class), 2);
return accounts.get(0);
}
/**
* 修改
*/
public void updateById(){
String sql = "update caogao set username = ?, password = ? where id = ?";
getJdbcTemplate().update(sql, "fff123", "fff123", 2);
}
/**
* 添加信息
*/
public void add(){
String sql = "insert into caogao(username, password) values(?,?)";
getJdbcTemplate().update(sql, "psq", "123");
}
/**
* 删除信息
*/
public void delete(){
String sql = "delete from caogao where id = ?";
getJdbcTemplate().update(sql, 7);
}
}
第一步:导入必备的 jar 包到工程中
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.0.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.hamcrestgroupId>
<artifactId>hamcrest-coreartifactId>
<version>1.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.27version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.6version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>2.1_3version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
dependencies>
第二步:创建 spring 的配置文件并导入约束
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
beans>
第三步:编写业务层接口和实现类
//业务层接口
public interface IAccountService {
//查询所有
List<Account> findAll();
//按 id 查询
Account findById(int id);
//按 username 查询
Account findByName(String username);
//添加信息
void saveAccount(Account account);
//修改信息
void updateAccount(Account account);
//按 id 删除信息
void deleteById(int id);
//交换信息
void changeMessage(String username1, String username2);
}
//业务层实现类
public class AccountServiceImpl implements IAccountService {
private AccountDaoImpl accountDao;
public void setAccountDao(AccountDaoImpl accountDao) {
this.accountDao = accountDao;
}
/**
* 查询所有信息
*/
public List<Account> findAll() {
return accountDao.findAll();
}
/**
* 按 id 查询信息
*/
public Account findById(int id) {
return accountDao.findById(id);
}
/**
* 按 username 查询信息
*/
public Account findByName(String username) {
return accountDao.findByName(username);
}
/**
* 添加信息
*/
public void saveAccount(Account account) {
accountDao.saveAccount(account);
}
/**
* 修改信息
*/
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
/**
* 删除信息
*/
public void deleteById(int id) {
accountDao.deleteById(id);
}
/**
* 交换信息,将 username1 和 username2 的名字交换
*/
public void changeMessage(String username1, String username2) {
accountDao.changeMessage(username1, username2);
}
}
第四步:编写持久层接口和实现类
//持久层接口
public interface IAccountDao {
//查询所有
List<Account> findAll();
//按 id 查询
Account findById(int id);
//按 username 查询
Account findByName(String username);
//添加信息
void saveAccount(Account account);
//修改信息
void updateAccount(Account account);
//按 id 删除信息
void deleteById(int id);
//交换信息
void changeMessage(String username1, String username2);
}
//持久层实现类
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountService {
/**
* 查询所有信息
*/
public List<Account> findAll() {
List<Account> accounts = super.getJdbcTemplate().query("select * from caogao", new BeanPropertyRowMapper<Account>(Account.class));
return accounts;
}
/**
* 按 id 查询信息
*/
public Account findById(int id) {
List<Account> accounts = super.getJdbcTemplate().query("select * from caogao where id=?", new BeanPropertyRowMapper<Account>(Account.class), 2);
return accounts.isEmpty() ? null : accounts.get(0);
}
/**
* 按 username 查询信息
*/
public Account findByName(String username) {
List<Account> accounts = super.getJdbcTemplate().query("select * from caogao where username=?", new BeanPropertyRowMapper<Account>(Account.class), username);
return accounts.isEmpty() ? null : accounts.get(0);
}
/**
* 添加信息
*/
public void saveAccount(Account account) {
super.getJdbcTemplate().update("insert into caogao(username, password) values(?,?)", account.getUsername(), account.getPassword());
}
/**
* 修改信息
*/
public void updateAccount(Account account) {
super.getJdbcTemplate().update("update caogao set username=?, password=? where id=?", account.getUsername(), account.getPassword(), account.getId());
}
/**
* 删除信息
*/
public void deleteById(int id) {
super.getJdbcTemplate().update("delete from caogao where id=?", id);
}
/**
* 交换信息,将 username1 和 username2 的信息交换
*/
public void changeMessage(String username1, String username2) {
//1、查询 username1 的信息
Account user1 = findByName(username1);
//2、查询 username2 的信息
Account user2 = findByName(username2);
//3、修改 username1 的信息
user1.setUsername(username2);
//4、修改 username2 的信息
user2.setUsername(username1);
//5、更新 username1 的信息
updateAccount(user1);
//模拟网络错误
int i = 10 / 0;
//6、更新 username2 的信息
updateAccount(user2);
}
}
第五步:在配置文件中配置业务层和持久层对
<bean id="accountService" class="cn.itfzk.spring09.service.impl.AccountServiceImpl" >
<property name="accountDao" ref="accountDao" >property>
bean>
<bean id="accountDao" class="cn.itfzk.spring09.dao.impl.AccountDaoImpl" >
<property name="dataSource" ref="dataSource">property>
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="driverClass" value="com.mysql.jdbc.Driver" >property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/fzk" >property>
<property name="user" value="root" >property>
<property name="password" value="123456" >property>
bean>
第六步: 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
第七步:配置事务的通知引用事务管理器 tx:advice
<tx:advice id="txAdvice" transaction-manager="transactionManager">
tx:advice>
第八步:配置事务的属性 tx:attributes、tx:method
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true">tx:method>
tx:attributes>
tx:advice>
第九步:配置 AOP 切入点表达式 aop:config、aop:pointcut
<aop:config>
<aop:pointcut id="pt" expression="execution(* cn.itfzk.spring09.service.impl.AccountServiceImpl.*(..))"/>
aop:config>
第十步:配置切入点表达式和事务通知的对应关系 aop:advisor
<aop:config>
<aop:pointcut id="pt" expression="execution(* cn.itfzk.spring09.service.impl.AccountServiceImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt">aop:advisor>
aop:config>
作用:事务的通知
属性:
<tx:advice id="txAdvice" transaction-manager="transactionManager">
tx:advice>
作用:事务的属性
属性:
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true">tx:method>
<tx:method name="" isolation="" propagation="" read-only="" timeout="" rollback-for="" no-rollback-for="">tx:method>
tx:attributes>
作用:建立事务通知和切入点表达式的对应关系
<aop:config>
<aop:pointcut id="pt" expression="execution(* cn.itfzk.spring09.service.impl.AccountServiceImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt">aop:advisor>
aop:config>
第一步:导入必备的 jar 包到工程中
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.0.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.hamcrestgroupId>
<artifactId>hamcrest-coreartifactId>
<version>1.3version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.27version>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.6version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>cglibgroupId>
<artifactId>cglibartifactId>
<version>2.1_3version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
dependencies>
第二步:创建 spring 的配置文件并导入约束
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
beans>
第三步:创建业务层接口和实现类并使用注解让 spring 管理
@Service("accountService") //使用注解让 spring 管理
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
public void changeAccount(int id1, int id2){
Account account1 = accountDao.findById(id1);
Account account2 = accountDao.findById(id2);
String name = account1.getUsername();
account1.setUsername(account2.getUsername());
account2.setUsername(name);
accountDao.update(account1);
int i = 10 / 0;
accountDao.update(account2);
}
}
第四步:创建持久层接口和实现类并使用注解让 spring 管理
@Repository("accountDao") //使用注解让 spring 管理
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
}
第五步:配置事务管理器并注入数据源
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
第六步:在业务层使用@Transactional 注解
@Service("accountService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = false) //使用@Transactional 注解
public class AccountServiceImpl implements IAccountService {
}
第七步:在配置文件中开启 spring 对注解事务的支持
<tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>
@Configuration
@EnableTransactionManagement //TransactionManagement
public class SpringTxConfiguration {
}