一、练习sop的编程,理解面向对象编程的含义
(一)了解AOP
AOP,面向切面编程。首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务;所谓的周边功能,比如性能统计,日志,事务管理等等,周边功能在Spring的面向切面编程AOP思想里,即被定义为切面;在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发,然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP。
(二)思路图
1. 功能分两大类,辅助功能和核心业务功能
2. 辅助功能和核心业务功能彼此独立进行开发
3. 比如登陆功能,即便是没有性能统计和日志输出,也可以正常运行
4. 如果有需要,就把"日志输出" 功能和 "登陆" 功能 编织在一起,这样登陆的时候,就可以看到日志输出了
5. 辅助功能,又叫做切面,这种能够选择性的,低耦合的把切面和核心业务功能结合在一起的编程思想,就叫做切面编程
(三)练习
1、准备业务类 ProductService
2、TestSpring:在引入切面之前,调用该业务类
3、准备日志切面 LoggerAspect:该日志切面的功能是在调用核心功能之前和之后分别打印日志。
4、applicationContext.xml
①声明业务对象
<bean name="s" class="com.how2java.service.ProductService">
</bean>
②声明日志切面
<bean id="loggerAspect" class="com.how2java.aspect.LoggerAspect"/>
③结合思路图指定右边的核心业务功能以及指定左边的辅助功能,然后通过aop:config把业务对象与辅助功能编织在一起。
<aop:pointcut id="loggerCutpoint"
expression=
"execution(* com.how2java.service.ProductService.*(..)) "/>
<aop:aspect id="logAspect" ref="loggerAspect">
<aop:around pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>
5、TestSpring
注:TestSpring代码没有发生任何变化,只是通过配置的方式,把切面和核心业务类编制在了一起。运行结果如下,在编织之后,业务方法运行之前和之后分别会打印日志。
二、练习教材案例,体会编程式事务管理
此次练习的主要步骤:
1、编写Manager类用来装载配置文件,利用spring IOC创建TransactionExample对象并执行TransactionExample类的transactionOperation方法
package com.mr.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mr.transaction.TransactionExample;
public class Manager {
public static void main(String[] args) {
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
TransactionExample transactionExample = (TransactionExample) factory.getBean("transactionExample");
transactionExample.transactionOperation();
}
}
2、编写TransactionExample类:用setter,getter方法注入数据源,事务管理器与TransactionTemplate模板,并定义添加数据的方法,在方法中执行两次添加数据库操作操作并用事务保护操作
package com.mr.transaction;
import java.sql.Connection;
import java.sql.Statement;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
public class TransactionExample {
DataSource dataSource;
PlatformTransactionManager transactionManager;
TransactionTemplate transactionTemplate;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public PlatformTransactionManager getTransactionManager() {
return transactionManager;
}
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public TransactionTemplate getTransactionTemplate() {
return transactionTemplate;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
public void transactionOperation() {
transactionTemplate.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
Connection conn = DataSourceUtils.getConnection(dataSource);
try {
Statement stmt = conn.createStatement();
stmt.execute("insert into tb_user(name,age,xingbie) values('jinghua','23','男')");
int a=0;
a=9/a;
stmt.execute("insert into tb_user(name,age,xingbie) values('xi','18','男')");
System.out.println("操作执行成功!");
} catch (Exception e) {
transactionManager.rollback(status);//事务回滚
System.out.println("操作执行失败,事务回滚!");
System.out.println("原因:"+e.getMessage());
}
return null;
}
});
}
}
3、编写配置文件:定义数据源,连接数据库的配置;定义事务管理器;定义TransactionExample模板;并为TransactionExample注入数据源 、事务管理器、TransactionTemplate模板
<?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-2.5.xsd">
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/test
</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>wal6775374wal</value>
</property>
</bean>
<!-- 定义TransactionTemplate模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRED</value>
</property>
</bean>
<!-- 定义事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 为TransactionExample注入数据源 、事务管理器、TransactionTemplate模板-->
<bean id="transactionExample"
class="com.mr.transaction.TransactionExample">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionTemplate">
<ref bean="transactionTemplate"/>
</property>
</bean>
</beans>
为了测试事务是否配置成功,在transactionOperation方法中执行两次添加操作之间添加制造人为的异常(int a=0;a=9/a;),即当第一条操作语句执行成功后,第二条操作语句因为程序的异常无法执行成功。如果此时事务回滚成功,说明事务配置成功。
输出事务回滚,说明事务配置成功,且表中并未插入数据。
三、练习教材案例,体会声明式事务管理
练习中的主要步骤:
1、编写配置文件:定义数据源、连接数据库的配置;定义事务管理器;定义TransactionProxy,并将事务管理器注入其中,设置代理对象和事务属性,且这里以内部类的形式指定代理的目标对象。
<?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-2.5.xsd">
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/test</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>wal6775374wal</value>
</property>
</bean>
<!-- 定义事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 定义TransactionProxy -->
<bean id="transactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager" />
</property>
<property name="target">
<!-- 以内部类的形式指定代理的目标对象 -->
<bean id="addDAO" class="com.mr.dao.AddDAO">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
</property>
<property name="proxyTargetClass" value="true" />
<property name="transactionAttributes">
<props>
<!-- 通过正则表达式匹配事务性方法,并指定方法的事务属性,即代理对象中只要是以add开头的方法名必须运行在事务中 -->
<prop key="add*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans>
2、编写AddDAO类:编写两次数据插入操作的方法,并在配置TransactionProxyFactoryBean时被定义为事务性方法,所以该方法中所有数据库操作都被当作一个事务处理。并在其中制造异常测试事务是否配置成功,与上个练习类似。
package com.mr.dao;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.mr.user.User;
public class AddDAO extends JdbcDaoSupport {
//添加用户的方法
public void addUser(User user){
//执行添加方法的sql语句
String sql="insert into tb_user (name,age,xingbie) values('" +
user.getName() + "','" + user.getAge()+ "','" + user.getSex()+ "')";
//执行两次添加方法
getJdbcTemplate().execute(sql);
int a=0;//制造异常测试事务是否配置成功
a=9/a;
getJdbcTemplate().execute(sql);
}
}
3、编写Manager类:装载配置文件,获取AddDAO,实例化User实体对象并设置姓名、年龄、性别,调用addUser方法执行数据库添加方法。
package com.mr.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mr.dao.AddDAO;
import com.mr.user.User;
public class Manager {
public static void main(String[] args) {
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml"); //装载配置文件
AddDAO addDAO = (AddDAO)factory.getBean("transactionProxy");//获取AddDAO
User user = new User();//实例化User实体对象
user.setName("huaxi");//设置姓名
user.setAge(18);//设置年龄
user.setXingbie("男");//设置性别
addDAO.addUser(user);//执行数据库添加方法
}
}
4、User.java
package com.mr.user;
public class User {
private String name;//姓名
private Integer age;//年龄
private String xingbie;//性别
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getXingbie() {
return xingbie;
}
public void setXingbie(String xingbie) {
this.Xingbie = xingbie;
}
}