AOP基本概念、AOP底层实现原理、AOP经典应用【事务管理、异常日志处理、方法审计】
1 什么是AOP
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2 通过配置实现AOP编程
2.1 导包
2.2 编写切面类(其实就是一个类)
package cn.xiangxu.cloudNote.aspect; public class AspectDemo01 {
public void logController() {
System.out.println("AOP功能注入Controller");
}
}
2.3 配置切面组件
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <!-- 案例:将AspectDemo01组件的logController方法作用与controller包及其自爆中所有方法 -->
<!-- 配置切入功能类的bean组件 -->
<bean id="aspectDemo01" class="cn.xiangxu.cloudNote.aspect.AspectDemo01"></bean>
<!-- AOP配置 -->
<aop:config>
<!-- 指定切面组件,通过ref属性进行关联 -->
<aop:aspect ref="aspectDemo01">
<!-- 通过method指定处理方法 -->
<!-- 通过poincut指定切入点 -->
<!-- within为类限定表达式 -->
<aop:before method="logController" pointcut="within(cn.xiangxu.cloudNote.controller..*)"></aop:before>
</aop:aspect>
</aop:config> </beans>
3 通过注解实现AOP编程
3.1 导包
3.2 创建切面类(在类中添加相关注解)
package cn.xiangxu.cloudNote.aspect; import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; @Component
@Aspect
public class AspectDemo02 {
// @Before(value = "within(cn.xiangxu.cloudNote.service..*)") // service包及其子包中的所有方法
// @Before(value = "within(cn.xiangxu.cloudNote.service.*)") // service中的所有方法(子包中的除外)
@Before(value = "within(cn.xiangxu.cloudNote.service.NoteServiceImpl)") // NoteServiceImpl类中的所有方法 public void serviceAspect() {
System.out.println("给笔记相关的业务实现类添加切面");
} // @Before("execution(* cn.xiangxu.cloudNote.service..*.*(..))") // service包及其子包下的所有方法(方法的返回值和参数没有限制)
@Before("execution(* cn.xiangxu.cloudNote.service.ShareSerive.shareNote(String))") // 指定方法名以及参数
public void shareAspect() {
System.out.println("给分享笔记方法添加切面");
} @Before("bean(*Dao)")
public void daoAspect() {
System.out.println("给所有持久层方法添加切面");
} }
@Component 代替在配置文件中配置bean
@Aspect 说明该类中的代码是一个切面的组件;等价于在配置文件中配置指定切面组件 <aop:aspect ref="loggerBean">
@Before(value = "within(cn.xiangxu.cloudnote.service..*)") 代替在配置文件中配置通知和切入点配置
3.3 在配置文件中配置注解扫描和启动AOP注解
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <!-- 扫描组件 -->
<context:component-scan base-package="cn.xiangxu.cloudNote.aspect"></context:component-scan>
<!-- 启动aop注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
4 AOP编程三要素
切面:追加啥? 就是追加我们单独封装的切面代码
通知:啥时候切入? (前置/后置/异常/最终/环绕)
切入点:切谁? (三种表达式:方法/类型/Bean限定表达式)
4.1 切面(Aspect)
指的是封装了共同处理的组件,即切面代码
4.2 通知(Before/AfterReturning/AfterThrowing/After/Around)
就是指定且面儿在哪里执行
try{
前置通知(@Before)
//执行组件方法
后置通知(@AfterReturning)
}catch{
异常通知(@AfterThrowing)
}finally{
最终通知(@After)
}
环绕通知(@Around)
4.3 切入点
4.3.1 切入点 Pointcut
用于指定目标方法 ,利用配置文件配置的写法为:pointcut="within(cn.xiangxu.cloudnote.controller..*)
如果利用注解的方式进行AOP编程,那么就会将切入点用表达式来代替并且写入通知中
4.3.2 表达式
4.3.2.1 方法限定表达式 execution
为某个组件的部分方法追加功能
execution(【修饰符】 返回类型 方法名(参数列表)) 【抛出异常】
execution(* add*(..))
匹配的是所有以add开头的方法,方法的返回值和参数可以是任意
execution(* cn.xiangxu.cloudnote.service.UserService.*(..))
匹配的是在UserService组件下的所有方法,方法的返回值和参数可以是任意
execution(* cn.xiangxu.cloudnote.service.*.*(..))
匹配的是service下所有组件的所有方法
execution(* cn.xiangxu.cloudnote.service..*.*(..))
匹配的是service包以及子包下所有组件的所有方法s
4.3.2.2 类限定表达式 within
within(cn.xiangxu.cloudnote.service.UserService)
匹配UserService组件下的所有方法
within(cn.xiangxu.cloudnote.service.*)
匹配service包下所有类的所有方法
within(cn.xiangxu.cloudnote.service..*)
匹配到service包及子包下的所有类的所有方法
4.3.2.3 bean限定表达式 bean(id名)
bean(userService)
匹配userService组件的所有方法
bean(*Service)
匹配以Service结尾的组件的所有方法
例子
@Before("bean(userController)")
5 AOP实现原理
动态代理
AOP底层实现是通过动态代理技术实现的
动态代理技术:动态创建类的技术
两种动态代理技术:
基于接口的(java.reflect.Proxy):实现接口,重写了接口中的方法
public class $Proxy23 implements UserService {
事务处理 + login()处理
将事务处理和login()处理整合到login()方法中
}
通过动态代理创建了一个新的类型
基于类的(CGLIB包):继承类,重写类中的方法
6 AOP经典应用
事务管理
方法审计
异常日志处理
6.1 案例:实现性能审计
切面:输出消耗时间
切入点:service下的所有方法
通知:环绕(@Around)
package cn.xiangxu.cloudNote.aspect; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; @Component
@Aspect
public class AuditBean {
@Around("within(cn.xiangxu.cloudNote.service..*)") // 所有业务层添加切面
public Object log(ProceedingJoinPoint point) throws Throwable {
Object obj = new Object();
try {
Long startTime = System.currentTimeMillis();
obj = point.proceed(); // point.proceed()代表某个方法的执行
Long endTime = System.currentTimeMillis();
String str = point.getSignature().toString(); // 获取执行方法签名
System.out.println(str + "耗时:" + (endTime - startTime));
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
} return obj;
}
}
6.2 案例:异常信息写入日志
要求:当service处理发生异常的时候,将异常信息写入文件中(利用AOP实现)
切面:将异常信息写入文件(FileWriter--PrintWriter)
切入点:service下的所有方法
通知:异常(@AfterThrowing)
package cn.xiangxu.cloudNote.aspect; import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date; import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; @Component
@Aspect
public class ExceptionBean {
// e : 表示目标组件方法抛出的异常对象
@AfterThrowing(throwing="e", pointcut="within(cn.xiangxu.cloudNote..*)")
public void execute(Exception e) {
try {
System.out.println("hello world");
// 创建日志文件 ("D:\\note_error.log") /home/soft01/note_error.log
FileWriter fw = new FileWriter("D:/note_error.log", true);
// 利用PrintWriter对象写入信息
PrintWriter pw = new PrintWriter(fw);
// 定义时间字符串
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time_str = sdf.format(date);
// 写入异常信息
pw.println("**********************");
pw.println("==异常类型:" + e);
pw.println("==发生时间:" + time_str);
pw.println("==异常详细信息==");
e.printStackTrace(pw);
pw.println("**********************");
pw.close();
fw.close(); } catch (Exception e2) {
// TODO: handle exception
System.out.println("记录异常失败");
}
}
}
6.3 事务管理
6.3.1 事务
程序为了保证业务处理的完整性,执行的一条或者多条SQL语句
6.3.2 事务管理
对事务中的SQL语句进行提交或者回滚
6.3.3 为什么要使用事务管理
确保数据库的完整性,不出现脏数据
6.3.4 事务回顾
oracle:commit/rollback (DML操作)
jdbc:默认是自动commit
6.3.5 怎么使用事务管理
》编程式事务管理
利用jdbc连接数据库就是使用的编程式事务管理
try{
业务SQL01
业务SQL02
业务SQL03
conn.commit();
}catch(Exception e) {
conn.rollback();
}
》声明式事务管理
》》在配置文件中配置spring事务管理
》》》定义事务管理的bean
org.springframework.jdbc.datasource.DataSourceTransactionManager
》》》开启注解
@Transactional
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"> <!-- Spring 事务处理 -->
<!-- 定义事务管理的Bean -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dbcp"></property>
</bean>
<!-- 开启@Transactional -->
<tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven> </beans>
》》使用注解标记@Transactional (加到类上就表示对所有的方法都进行事务管理,加到方法上就表示只对该方法进行事务管理)
6.3.6 @Transactional新特性
@Transactional标记的特性
可读可写:readOnly
作用于select语句的事务上
语法
@Transactional(readOnly=true)
回滚特性:rollBackFor
用于指定回滚的异常类型,因为默认只对运行异常进行处理
语法
@Transactional(rollBackFor=异常类型)
传播特性
@Transactional
public void fn1() {
业务1处理
fn2() // 如果fn2()出现错误,就会对业务1进行回滚
业务2处理
} @Transactional
public void fn2() {
业务3处理
} 隔离特性
为解决并发访问数据库问题而设计的
脏读:事务一进行了增删改操作,但并未提交;此时事务二读取了事务操作的数据;此时,
事务一进行了回滚,那么我们就说事务二进行了一次脏读操作
幻读:事务一在一定范围内查询数据,同时事务二在该范围内又增加了数据,这种现象我们
就说事务一做了一次幻读
AOP基本概念、AOP底层实现原理、AOP经典应用【事务管理、异常日志处理、方法审计】的更多相关文章
- Spring AOP基础概念及自定义注解式AOP初体验
对AOP的理解开始是抽象的,看到切点的匹配方式其实与正则表达式性质大致一样就基本了解AOP是基本是个什么作用了.只是整个概念更抽象,需要具化理解.下图列表是AOP相关概念解释,可能也比较抽象^_^ 比 ...
- Java AOP的底层实现原理
Java AOP的底层实现原理 一.什么是AOP 1.AOP:Aspect Oriented Programming(面向切面编程),OOP是面向对象编程,AOP是在OOP基础之上的一种更高级的设计思 ...
- Spring AOP入门——概念和注意事项
AOP什么? AOP在功能方面,它是之前和之后运行一些业务逻辑,一些操作(比方记录日志.或者是推断是否有权限等),这些操作的加入.全然不耦合于原来的业务逻辑.从而对原有业务逻辑全然是透明. 也就是说. ...
- 二十 Spring的事务管理及其API&事务的传播行为,编程式&声明式(xml式&注解式,底层AOP),转账案例
Spring提供两种事务方式:编程式和声明式(重点) 前者需要手写代码,后者通过配置实现. 事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACI ...
- spring事务管理方式,aop
达内12 note unit 09 01 1.spring事务管理 2.spring提供了对事务管理支持 spring采用aop机制完成事务控制 可以实现在不修改原有组件代码情况下实现事务控制功能. ...
- Spring 事务管理tx,aop
spring tx:advice事务配置 2016年12月21日 17:27:22 阅读数:7629 http://www.cnblogs.com/rushoooooo/archive/2011/08 ...
- 基于 <tx> 和 <aop> 命名空间的声明式事务管理
环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加方法: 点击项目右键->Build Path->Add ...
- Spring 事务管理原理探究
此处先粘贴出Spring事务需要的配置内容: 1.Spring事务管理器的配置文件: 2.一个普通的JPA框架(此处是mybatis)的配置文件: <bean id="sqlSessi ...
- Spring系列.事务管理原理简析
Spring的事务管理功能能让我们非常简单地进行事务管理.只需要进行简单的两步配置即可: step1:开启事务管理功能 @Configuration //@EnableTransactionManag ...
随机推荐
- (七)js函数一
1.函数概念:函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块. 语法:fuction hello(){ code... } a)手动驱动: eg: hello(); ...
- JDBC 4 PreparedStatement 与Statement 的区别
1 有安全性 PreparedStatement 可以由于不是使用拼接,防止了sql注入,提高了安全性. 2 更方便 PreparedStatement 可以自动对类型进行转换,代码可读性,可维护 ...
- Servlet中的Filter(过滤器)
Filter,过滤器,是处于客户端与服务器资源文件之间的一道过滤网,在访问资源文件之前,通过一系列的过滤器对请求进行修改.判断等,把不符合规则的请求在中途拦截或修改.也可以对响应进行过滤,拦截或修改 ...
- STM32GPIO管脚设置
(1)GPIO_Mode_AIN 模拟输入 (2)GPIO_Mode_IN_FLOATING 浮空输入(3)GPIO_Mode_IPD 下拉输入 (4)GPIO_Mode_IPU 上拉输入 (5)GP ...
- Java文件压缩优化工具(ProGuard) 软件介绍 Soft content
ProGuard是一款免费的Java类文件的压缩.优化.混肴器.它可以帮你删除没用的类,字段,方法与属性,使字节码最大程度地优化,使用简短且无意义的名字来重命名类.字段和方法 .目前eclipse已经 ...
- 使用妹子UI开发的体验分享
前阵子看到一个类似bootstrap的前端UI框架,好奇心驱使下,去琢磨了一些,最终决定网站改版用这个UI试试效果: 首页+头部: 投稿页: 现成拷贝过来的评论列表: 总结: 上手难度: (熟悉boo ...
- 蓝桥杯 算法训练 ALGO-114 黑白无常
算法训练 黑白无常 时间限制:1.0s 内存限制:256.0MB 问题描述 某寝室的同学们在学术完之后准备玩一个游戏:游戏是这样的,每个人头上都被贴了一张白色或者黑色的纸,现在每个人都会说一句 ...
- .net中webconfig自定义配置
在configuration节点,也就是文件的根节点下,增加如下节点 <appSettings> <!--<add key="propPath" value ...
- 使用Visual Studio开发跨平台的iOS应用程序
[原文发表地址]Developing cross-platform iOS application using Visual Studio [原文发表时间]2015/6/4 C ++是一种流行的高级编 ...
- Velodyne 线性激光雷达数据合成
坐标系旋转 如果想用字母表示角度,有两个方法: 1. 用三角函数sind(θ4).cosd(θ4).tand(θ4).atand(θ4)进行表示,注意:θ4在输入时是角度,只是没有度数特有的符号(° ...