1 案例
需求: 完成转账业务, 事务的支持:

1.1开发数据库表:Account id name money、
开发实体类: Account
public class Account {
private Integer id;
private String name;
private double money;
}
1.2开发AccountDao ; 查询, 更新方法:
package com.yidongxueyuan.spring.dao;

import com.yidongxueyuan.spring.pojo.Account;

public interface AccountDao {
/**
* 查询用户:
* @param accountName
* @return
*/
Account findAccountByName(String accountName);

/*** 更新操作: * @param newAccount*/
void updateAccount(Account newAccount);

}
1.3开发AccountDaoImpl ; DBUtils链接数据库。
package com.yidongxueyuan.spring.dao.impl;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import com.yidongxueyuan.spring.dao.AccountDao;
import com.yidongxueyuan.spring.pojo.Account;
import com.yidongxueyuan.spring.utils.TransactionManager;

public class AccountDaoImpl implements AccountDao {

//获得对象, 不需要给出数据源: private QueryRunner qr= new QueryRunner();@Overridepublic Account findAccountByName(String accountName) {try {String sql ="select * from account where name =?";Account account = qr.query(TransactionManager.getConnection(), sql, new BeanHandler<Account>(Account.class),accountName);return account;} catch (SQLException e) {e.printStackTrace();}return null; }@Overridepublic void updateAccount(Account newAccount) {try {String sql ="update account set money = ? where name =?";qr.update(TransactionManager.getConnection(), sql, newAccount.getMoney(),newAccount.getName());} catch (SQLException e) {e.printStackTrace();}}

}
1.4开发AccountService ; 定义业务方法: transfer
package com.yidongxueyuan.spring.service;

public interface AccountService {
/**
* 业务方法, 实现转账
* @param sourceAccount 来源账户
* @param targetAccount 目标账户
* @param money 转账金额
*/
public void transfer(String sourceAccount,String targetAccount,float money);
}

1.5开发AccountServiceImpl实现类:
package com.yidongxueyuan.spring.service.impl;

import com.yidongxueyuan.spring.dao.AccountDao;
import com.yidongxueyuan.spring.dao.impl.AccountDaoImpl;
import com.yidongxueyuan.spring.pojo.Account;
import com.yidongxueyuan.spring.service.AccountService;

public class AccountServiceImpl implements AccountService{
private AccountDao dao= new AccountDaoImpl();
@Override
public void transfer(String sourceAccount, String targetAccout, float money) {

     //开启事务: //根据来源账户: Account sourceAcc = dao.findAccountByName(sourceAccount);//aaa//查询目标账户: Account targetAcc = dao.findAccountByName(targetAccout);// ccc//来源账户减钱sourceAcc.setMoney(sourceAcc.getMoney()-money); //目标账户增钱:targetAcc.setMoney(targetAcc.getMoney()+money);//调用dao层的方法: 将变化后的数据保存哎数据库当中: dao.updateAccount(sourceAcc);//模拟异常的发生: int i=1/0;dao.updateAccount(targetAcc);}

}

1.6工具类: 获得数据源的工具类
package com.yidongxueyuan.spring.utils;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Util {
/**
* 初始化一个对象:
* ComboPooledDataSource 是DataSource类的子类对象:
*/
private static DataSource ds = new ComboPooledDataSource();

/*** 返回一个数据源: * @return*/
public static DataSource getDataSource(){return ds;
}/*** 获得一个链接对象: * @return Connection链接对象: */
public static Connection getConnection(){try {return ds.getConnection();} catch (SQLException e) {e.printStackTrace();}return null;
}

}

1.7工具类依赖的配置文件

<?xml version="1.0" encoding="UTF-8"?> com.mysql.jdbc.Driver jdbc:mysql:///customer root root 10 30 100 10 200

1.8测试
public class TestAccountService {
@Test
public void test1() {
//直接获得被代理对象:
AccountService service = new AccountServiceImpl();
service.transfer(“aaa”, “ccc”, 100);
}

}

测试总结: 在没有加入事务的前提下, 转账的过程当中: aaa 用户-100 但是ccc用户钱并没有增加: 不符合实际情况。 所以加入事务的支持。 保证转账的一个逻辑单元要么都成功, 要么都失败。

1.9 使用aop的方式事务
获得UserServiceImpl类的代理类对象; 在执行业务方法的时候, 在动态的加入事务的支持。

package com.yidongxueyuan.spring.utils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.yidongxueyuan.spring.service.AccountService;
import com.yidongxueyuan.spring.service.impl.AccountServiceImpl;

/**

  • 定义一个工厂: 获得对象的代理对象:
  • @author Mrzhang

*/
public class BeanFactory {

/*** 定义了一个方法: 能够获得业务对象的代理对象: * @return*/
public static AccountService getProxy(){//被代理的对象: final AccountService service = new AccountServiceImpl();//只专注于转账://获得代理类: AccountService proxy= (AccountService)Proxy.newProxyInstance(//代理类的类加载器service.getClass().getClassLoader(), //代理类的接口当中所有的方法: service.getClass().getInterfaces(),//InvocationHandler 接口: 定义代理类和被代理类的具体的代理策略: new InvocationHandler() {//proxy:代理类引用: // method:当前执行的方法: // args:执行方法的参数//Object 调用方法的返回值: : @Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object obj =null; try {//事务开启: TransactionManager.startTransaction();//调用业务方法: obj = method.invoke(service, args);//事务的提交: TransactionManager.commit();} catch (Exception e) {TransactionManager.rollback();e.printStackTrace();} finally{//释放资源:}return obj;}});return proxy;
}

}
1.10测试:
@Test
public void test1() {
//直接获得被代理对象:
AccountService service = new AccountServiceImpl();
//获得service类的代理类对象:
AccountService proxy = BeanFactory.getProxy();
proxy.transfer(“aaa”, “ccc”, 100);
}

2AOP
2.1 aop概述
Aop 面向切面编程,底层是动态代理实现的。 是oop的延伸。 解决了oop开发过程当中遇到的一些问题。
Aop可以解决: 事务管理 日志的记录 权限的校验 性能的监控。

2.2 代理模式
代理模式: 分类静态代理&动态代理:
静态代理:
动态代理:分类:
基于接口的动态代理: JDK
基于普通Bean的代理: CGLIB (第三方,使用时候导入jar)

2.3 spring当中AOP
Aop 面向切面编程的思想, 这思想并不是spring提出的。 spring当中引用了aop。

Spring框架: aop的实现:
(1)spring当中对aop进行了具体的实现: (废弃)
(2)Spring引用了 AspectJ 对aop进行了很好的实现。(广泛使用)

2.4 aop相关的数据

public interface UserDao {public User findUserById(int id);public void saveUser(User user);public void deleteUser(int id); public void updateUser(User user) ;}

连接点(join point ): 可以被拦截到的点就是连接点。
增删改查这些方法都有机会可以被进行功能性的增强, 这些方法都是连接点。

切入点(PonitCut): 真正被拦截到的点。
真正被增强的方法, 就称之为切入点。 在实际开发过程当中, saveUser方法被增强了, 此时saveUser这个方法就是切入点

通知(advice) :增强(方法层面的增强)
在执行saveUser方法之前, 要执行checkPri这个方法,此时checkPri这个方法就称之为通知, 也叫作增强。

引介: (Introduction) : 类层面的增强。

目标:(Target) : 被增强的对象:
在开发当中, UserDao 需要被增强, UserDao就是增强的对象。

织入:(Weaving) :将通知(advice)应用到目标(target)的过程
saveUser方法需要在执行之前加入checkPri()进行权限的校验,这个过程就是织入。

代理对象(Proxy): 目标被增强后,就是一个代理对象。

切面: (aspect): 多个通知和多个切入点的集合。 多个通知的集合。

2.5 aop的入门案例

2.5.1 引入aop相关的jar包:
IOC: 4个核心+ 2个日志:
注解式开发: spring3.x 不需要导入其他的》
Spring4.x 引来了aop
Aop的开发: 4个:


第一个jar: aop联盟
第二个jar: aspectweaving
第三个jar: aop
第四个jar: spring 整合aspect

Spring当中自己提供了一个套实现: 开发只需要两个: aop , aopalliance
Spring引入了aspect后: aspectJ spring-aspect :

2.5.2 核心配置文件当中引入相关的约束:

<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.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
</bean>

2.5.3 定义接口 UserDao
public interface UserDao {

public User findUserById(int id);public void saveUser(User user);public void deleteUser(int id); public void updateUser(User user) ;

}
2.5.4 定义接口的实现:

 UserDaoImpl
package com.yidongxueyuan.spring.dao.impl;import org.springframework.stereotype.Repository;import com.yidongxueyuan.spring.dao.UserDao;
import com.yidongxueyuan.spring.pojo.User;public class UserDaoImpl implements UserDao {@Overridepublic User findUserById(int id) {System.out.println("根据id 进行用户的查询:");return null;}@Overridepublic void saveUser(User user) {System.out.println("save...");}@Overridepublic void deleteUser(int id) {System.out.println("delete...");}@Overridepublic void updateUser(User user) {System.out.println("update...");}}

2.5.5 定义切面类 并且常见对象: (增强的集合)
package com.yidongxueyuan.spring.pojo;

/**

  • 定义一个切面: (通知的集合)
  • @author Mrzhang

*/
public class MyAspectXml {

/***  定义了一个通知: (增强)*/
public void checkPri() {System.out.println("权限的校验");
}

}

2.5.6 通过配置的方法, 实现对UserDaoImpl当中的方法进行功能的增强。
ApplicationContext.xml当中进行配置L:

 <!-- 配置切面类: --><bean id="myAspectXml" class="com.yidongxueyuan.spring.pojo.MyAspectXml"></bean> <!-- 目标类:  --><bean id="userDao" class="com.yidongxueyuan.spring.dao.impl.UserDaoImpl"></bean><!-- aop的配置:  aop: config 标签代表aop配置标签: aop:aspect: 开始配置切面: 通知和切点集合: id: 配置该切面的唯一标识: 自定义的: ref:引入切面类: aop:before: 在切点之前执行: method: 指定增强的方法: pointCut: 定义切点: 基于execution编写: --><aop:config><!-- 配置一个切点: --><!-- 配置切面: 通知和切入点的集合 --><aop:aspect id="myAspect" ref="myAspectXml"><aop:before method="checkPri"  pointcut="execution( * com.yidongxueyuan.spring.dao.impl.UserDaoImpl.saveUser(..))" /></aop:aspect></aop:config>·

总结配置: 将切面类当中的增强应用在目标类的切点上。

2.5.7测试 (spring整合Junit后)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestUserDao {//整合后的单元测试: @Resource(name="userDao")private UserDao userDao;@Testpublic void test2() throws Exception {userDao.saveUser(new User());}}

2.6 spring整合junit
(1)加入单元测试的包:

(2)使用JUnit:

package com.yidongxueyuan.spring.test;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.yidongxueyuan.spring.dao.UserDao;
import com.yidongxueyuan.spring.pojo.User;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestUserDao {//整合后的单元测试: @Resource(name="userDao")private UserDao userDao;@Testpublic void test2() throws Exception {userDao.saveUser(new User());}//传统的单元测试: @Testpublic void test1() throws Exception {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserDao dao = (UserDao)context.getBean("userDao");dao.saveUser(new User());}}

2.7 spring当中提供的通知的类型:
五种通知类型:
2.7.1前置通知:

   <!-- 配置切面: 通知和切入点的集合 --><aop:aspect id="myAspect" ref="myAspectXml"><aop:before method="checkPri"  pointcut="execution( * com.yidongxueyuan.spring.dao.impl.UserDaoImpl.saveUser(..))" /></aop:aspect>

2.7.2 后置增强:

总结: 当异常通知执行了, 后置通知就不再执行了。
2.7.3 最终通知

2.7.4 异常抛出通知

总结: 如果最后通知执行, 异常抛出通知不执行。

异常抛出通知, 能够获得异常信息:

public void afterThrow(Throwable e) {// e的名称必须和配置文件当中抛出的名称一致。System.out.println("异常抛出通知:  "+e.getMessage());//获得抛出的异常信息。
}

总结: 前置, 后置, 最终, 异常抛出通知, 以上四个通知不可能通知执行。 后置通知和异常抛出通知只能执行一个。
当没有遇到异常的时候, 执行后置通知。
遇到了异常信息, 执行异常抛出通知。

2.7.5 环绕通知
切面当中增强的定义:

/*** 测试了代码: 环绕通知执行了, 但是业务代码没有执行: * * spring当中提供了一个对象: ProceedingJoinPoint 放行业务代码:  方法有返回值: */public Object around(ProceedingJoinPoint joinPoint) {//放行业务代码: Object obj= null; try {System.out.println("前置通知。");obj= joinPoint.proceed();System.out.println("后置通知。");} catch (Throwable e) {System.out.println("异常抛出通知: ");e.printStackTrace();} finally {System.out.println("最终通知");}return obj; }
核心配置文件当中配置环绕通知: <aop:around method="around" pointcut="execution( * com.yidongxueyuan.spring.dao.impl.UserDaoImpl.saveUser(..))"  />测试。。。
总结: 环绕通知可以模拟前置,后置, 异常, 最终通知。 2.8 通用化切点的配置<aop:config><!-- 配置一个切点: 任何的切面都可以引用该切点:  --><aop:pointcut expression="execution( * com.yidongxueyuan.spring.dao.impl.UserDaoImpl.saveUser(..))" id="ponit1"/> <!-- 配置切面: 通知和切入点的集合 --><aop:aspect id="myAspect" ref="myAspectXml"><!-- 前置通知  --><aop:before method="checkPri"  pointcut-ref="ponit1"/><!-- 后置通知:  --><aop:after-returning method="writeLogger" pointcut-ref="ponit1" /> <!-- 最终通知:  --><aop:after method="after" pointcut-ref="ponit1"  />  <!-- 异常抛出通知 --><aop:after-throwing method="afterThrow" throwing="e" pointcut-ref="ponit1"  /></aop:aspect></aop:config>

2.9 execution 表达式的书写

  <aop:pointcut expression="execution( void com.yidongxueyuan.spring.dao.impl.UserDaoImpl.saveUser(..))" id="ponit1"/>

Expression: 基于execution的书写:

语法:
访问权限修饰符 返回值 包名.类名.方法的名称(方法参数的类型)

访问权限可以省略的:
void com.yidongxueyuan.spring.dao.impl.UserDaoImpl.saveUser(…))

返回值: 可以写成具体的返回值类型: void
返回值类型可以使用通配符: * :带表任何的返回值。

包: 可以使用统配符: * 每一个就代表一级包。
execution( * ..
...UserDaoImpl.saveUser(…))"
*… 代表当前当前包,
expression=“execution( * *…UserDaoImpl.saveUser(…))”
类: 可以使用统配: * 代表所有的类。
方法: 可以同时通配符: * 代表任意的方法。
方法的参数:
如果写具体的类型: 基本数据类型: int double
如果是引用类型: 必须写全限定类型: java.lang.String.class Java.lang.Integer.class
方法的参数可以使用通配符:
*:带表有参数:
() 匹配不带参数;
(…) 匹配带参数的和不带参数的。

总结: 在实际开发当中, 不需要写统配方法:
统配的写法:
expression=“execution( * .*(…))”

建议:

  • com.yidongxueyuan.xx.impl..(…)
    业务包下的所有的实现类。

spring中IOP的配置相关推荐

  1. spring中的事务配置

    为什么80%的码农都做不了架构师?>>>    一 简介 spring中提供了三种事务管理的方法. 编程式事务管理 :亦即自己编写事务管理的代码,通过注入获取到spring中的事务管 ...

  2. Quartz 在 Spring 中如何动态配置时间

    在项目中有一个需求,需要灵活配置调度任务时间,并能自由启动或停止调度. 有关调度的实现我就第一就想到了Quartz这个开源调度组件,因为很多项目使用过,Spring结合Quartz静态配置调度任务时间 ...

  3. Quartz 在 Spring 中如何动态配置时间--转

    原文地址:http://www.iteye.com/topic/399980 在项目中有一个需求,需要灵活配置调度任务时间,并能自由启动或停止调度.  有关调度的实现我就第一就想到了Quartz这个开 ...

  4. Spring中的Bean配置、属性配置、装配内容详细叙述

    文章目录 1.Bean的配置 1.1.配置方式 2.Bean的实例化 2.1.构造器实例化 2.2.静态工厂方式实例化 2.3.实例工厂方式实例化 3.Bean的作用域 3.1.作用域的种类 4.Be ...

  5. 在Spring中使用JDBCJobStore配置Quartz

    我将开始一些有关Quartz Scheduler内部,提示和技巧的系列文章,这是第0章-如何配置持久性作业存储. 在Quartz中,您基本上可以在将作业和触发器存储在内存中以及在关系数据库中进行选择( ...

  6. Spring中的Bean配置

    IOC&DI概述 OPC(Inversion of Control):其思想是反转资源获取的方向.传统的资源查找方式要求组件向容器发起请求查找资源.作为回应,容器适时的返回资源.而应用了IOC ...

  7. spring中MessageSource的配置使用方法3--ResourceBundleMessageSource

    ApplicationContext接口扩展了MessageSource接口,因而提供了消息处理的功能(i18n或者国际化).与HierarchicalMessageSource一起使用,它还能够处理 ...

  8. Spring中的scope配置和@scope注解

    Scope,也称作用域,在 Spring IoC 容器是指其创建的 Bean 对象相对于其他 Bean 对象的请求可见范围.在 Spring IoC 容器中具有以下几种作用域:基本作用域(single ...

  9. Spring讲解二:Spring中的Bean配置0

    一.IOC &DI 概述 IOC(Inversion of Control):思想是反转资源获取的方向.传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器适时的返回资源.而应用I ...

最新文章

  1. 操作系统学习:Linux0.12文件异步IO
  2. JS-用js的for循环实现九九乘法表以及其他算数题等
  3. 上海银行:转型创新网银与应用质量双赢
  4. Next.js踩坑入门系列(七) —— 其他相关知识
  5. 震惊!原来这才是Kafka的“真面目”!
  6. Python OS模块使用汇总
  7. 【完整代码】使用Semaphore实现限流代码示例
  8. redis smembersmap_【Redis】redis各类型数据存储分析
  9. 「Python基础知识」Python中常用的内建函数有哪些
  10. MyBatis 实现增删CRUD
  11. [Project Euler] 来做欧拉项目练习题吧: 题目013
  12. python随机森林筛选变量_如何使用虚拟变量来表示python scikit-learn随机森林中的分类数据...
  13. Windows xp Ms08067漏洞复现
  14. win7下强制结束进程的cmd命令
  15. VCC、VDD、VSS等是什么意思
  16. 集合添加元素python_集 - 百度文库
  17. 【echarts报错】: ‘normal‘ hierarchy in itemStyle has been removed since 4.0.
  18. 按键精灵学习如何偷菜示例基本代码
  19. 上标和下标复制大全(含0~9、字母、特殊字符)
  20. matlab闭式网络潮流计算,大工20秋《电力系统分析》在线作业2满分

热门文章

  1. MVC和MVVM框架介绍
  2. ESP8266 网络服务器仪表显示传感器读数
  3. Linux的判断两个字符串是否相等
  4. Go 使用IP纯真库获取IP对应的国家、省、市
  5. webstorm注册码
  6. 教育行业一般用什么邮箱,教育邮箱推荐
  7. 【FPGA算法加速】运行PYNQ,对应FPGA芯片版本:赛灵思黑金AX7020
  8. 第13章 项目合同管理
  9. 位、字节、字符的简介
  10. SQL 修改列的长度