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经典应用【事务管理、异常日志处理、方法审计】的更多相关文章

  1. Spring AOP基础概念及自定义注解式AOP初体验

    对AOP的理解开始是抽象的,看到切点的匹配方式其实与正则表达式性质大致一样就基本了解AOP是基本是个什么作用了.只是整个概念更抽象,需要具化理解.下图列表是AOP相关概念解释,可能也比较抽象^_^ 比 ...

  2. Java AOP的底层实现原理

    Java AOP的底层实现原理 一.什么是AOP 1.AOP:Aspect Oriented Programming(面向切面编程),OOP是面向对象编程,AOP是在OOP基础之上的一种更高级的设计思 ...

  3. Spring AOP入门——概念和注意事项

    AOP什么? AOP在功能方面,它是之前和之后运行一些业务逻辑,一些操作(比方记录日志.或者是推断是否有权限等),这些操作的加入.全然不耦合于原来的业务逻辑.从而对原有业务逻辑全然是透明. 也就是说. ...

  4. 二十 Spring的事务管理及其API&事务的传播行为,编程式&声明式(xml式&注解式,底层AOP),转账案例

    Spring提供两种事务方式:编程式和声明式(重点) 前者需要手写代码,后者通过配置实现. 事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACI ...

  5. spring事务管理方式,aop

    达内12 note unit 09 01 1.spring事务管理 2.spring提供了对事务管理支持 spring采用aop机制完成事务控制 可以实现在不修改原有组件代码情况下实现事务控制功能. ...

  6. Spring 事务管理tx,aop

    spring tx:advice事务配置 2016年12月21日 17:27:22 阅读数:7629 http://www.cnblogs.com/rushoooooo/archive/2011/08 ...

  7. 基于 <tx> 和 <aop> 命名空间的声明式事务管理

    环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加方法: 点击项目右键->Build Path->Add ...

  8. Spring 事务管理原理探究

    此处先粘贴出Spring事务需要的配置内容: 1.Spring事务管理器的配置文件: 2.一个普通的JPA框架(此处是mybatis)的配置文件: <bean id="sqlSessi ...

  9. Spring系列.事务管理原理简析

    Spring的事务管理功能能让我们非常简单地进行事务管理.只需要进行简单的两步配置即可: step1:开启事务管理功能 @Configuration //@EnableTransactionManag ...

随机推荐

  1. 深入学习Heritrix---解析Frontier(链接工厂)(转)

    深入学习Heritrix---解析Frontier(链接工厂) Frontier是Heritrix最核心的组成部分之一,也是最复杂的组成部分.它主要功能是为处理链接的线程提供URL,并负责链接处理完成 ...

  2. kali视频(16-20)学习

    第五周 kali视频(16-20)学习 16.漏洞分析之数据库评估(一) 17.漏洞分析之数据库评估(二) 18.漏洞分析之WEB应用代理 19.漏洞分析之burpsuite 20.漏洞分析之fuzz ...

  3. C# 操作自定义config文件

    示例文件:DB.config 1.读取 //先实例化一个ExeConfigurationFileMap对象,把物理地址赋值到它的 ExeConfigFilename 属性中: ExeConfigura ...

  4. 泛型List<T>排序(利用反射)

    在最近一个项目中,有需求要对页面中所有的gridview添加排序功能.由于gridview的数据源绑定的是一个集合类List,而不是DataTable,所以无法使用DataView排序功能.另外,不同 ...

  5. Linux bash shell 入门

    https://www.cnblogs.com/cosiray/archive/2012/03/02/2377099.html

  6. MyBatis缓存结构

    Mybatis Cache结构图: CacheKey(statementId, sql, sqlParams,other). 上图展示了Mybatis Cache的结构: 1)每个Mapper对应一块 ...

  7. mybatis返回Date类型数据 格式化

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") public Date getC ...

  8. php调试时echo,print_r(),var_dump()的区别

    简单说: var_dump() 能打印出类型 print_r() 只能打出值echo() 是正常输出... 需要精确调试的时候用 var_dump();一般查看的时候用 print_r() 另外 , ...

  9. BROCADE交换机配置

    BROCADE交换机配置一 与交换机交互,可以使用三种方式: 串口 以太网口 光纤口 缺省的串口参数是:9600,N,8,1 缺省IP访问方式是: IP地址: 10.77.77.77 用户名: adm ...

  10. volley 发送post请求

    public static void postNewComment(Context context,final UserAccount userAccount,final String comment ...