Spring学习框架之四(AOP)

AOP概念

Aspect Oriented Programming
被称为面向方面编程。OOP是面向对象编程,AOP是以OOP为基础。OOP主要关注的是对象,如何抽象和封装对象。AOP主要关注的是方面,方面组件可以以低耦合方式切入到其他某一批目标对象方法。AOP主要解决共通处理和目标组件之间解耦的问题。

AOP相关概念
方面(Aspect)

指的是封装了共通处理的功能组件,该组件可以作用到某一批目标组件的方法上

public class LoggerBean {
    //采用环绕通知
    public Object logger(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("--记录用户操作--");
        //前置逻辑
        //获取要执行的目标组件类名
        String clazz = proceedingJoinPoint.getTarget().getClass().getName();
        //获取要执行的方法名
        String mth = proceedingJoinPoint.getSignature().getName();
        /*System.out.println(clazz);
        System.out.println(mth);*/
        //根据类名和方法名,给用户提示具体操作信息
        String key = clazz+"."+mth;
        //解析obj.properties,根据key获取信息
        Object obj = proceedingJoinPoint.proceed();//执行目标方法
        //后置逻辑
        return obj;
    }
}
切入点(Pointcut)

指的是用于指定目标组件的表达式。方面组件和哪一批目标组件方法有关系。

<!-- 定义切入点,用于指定目标组件和方法 -->
        <aop:pointcut id = "actionPointcut" expression = "within(com.shagou.CostAction..*)"/>
连接点(JoinPoint)

切入点是连接点的集合。方面组件和具体哪一个目标的方法有关系。

通知(Advice)

用于指定方面组件和目标组件方法之间的作用时机。例如,先执行方面组件,再执行目标方法;或者,先执行目标方法,在执行方面组件。

<!-- 定义通知,用于指定先执行方面组件的logger方法,在执行切入点指定的目标方法,环绕通知 -->
            <aop:around pointcut-ref ="actionPointcut" method = "logger"/>
目标(Target)

利用切入点指定的组件和方法。

动态代理(AutoProxy)

Spring采用了动态代理技术实现了AOP机制。当使用了AOP之后,从容器getBean获取的目标组件,返回的是一个动态生成的代理类。然后通过代理类执行业务方法,代理类负责去调用方面组件功能和原目标组件功能。

Spring提供了下面两张动态代理技术实现:

采用CGLIB技术实现(目标组件没有接口采用此方法)

public class 代理类 extends 原目标类型{}
    CostAction CostAction = new 代理类();

采用JDK Proxy API实现(目标组件有接口采用此方法)

public class 代理类 implements 原目标接口{}
    CostDAO costDao = new 代理类();
<!-- AOP记录操作日志案例 -->
   <bean id = "loggerBean" class = "com.shagou.aop.LoggerBean"></bean>
   <aop:config>
   <!-- 定义切入点,用于指定目标组件和方法 -->
        <aop:pointcut id = "actionPointcut" expression = "within(com.shagou.CostAction..*)"/>
        <!-- 定义方面,引入上面的bean,将loggerBean对象指定为方面组件 -->
        <aop:aspect id = "loggerAspect" ref = "loggerBean">
        <!-- 定义通知,用于指定先执行方面组件的logger方法,在执行切入点指定的目标方法,环绕通知 -->
            <aop:around pointcut-ref ="actionPointcut" method = "logger"/>
        </aop:aspect>
   </aop:config> 
  • 通知类型
    通知类型方面组件和目标组件作用的关系,主要有以下几种类型通知
  • 前置通知:
    方面组件在目标方法之前执行
  • 后置通知:
    方面组件在目标方法之后执行,目标方法没有抛出异常才执行方面组件。
  • 最终通知:
    方面组件在目标方法之后执行,目标方法有没有异常都会执行方面组件。
  • 异常通知:
    方面组件在目标方法抛出异常后执行。
  • 环绕通知:
    方面组件在目标方法之前和之后执行。环绕通知等价于前置+后置
  • 切入点:
    切入点用于指定目标组件和方法。Spring提供了多种表达式的写法
  • 方法限定表达式
execution(修饰符? 返回类型  方法名(参数列表)throws 异常?)
    a.execution(public *  *  (..)) 匹配容器中所有public修饰的方法
    b.execution(       *  set*(..)) 匹配容器中方法以set开头的
    c.execution(    *     com.shagou.CostService.*(..)) 匹配CostService中所有方法
    d.execution(*         com.shagou.dao.*.*(..)) 匹配dao包下所有类所有方法
    e.execution(*         com.shagou.dao..*.*(..)) 匹配dao包及其子包中的所有类的所有方法
  • 类型限定表达式
within(类型)
    a.within(com.shagou.Service.*) 匹配Service包下的所有类所有方法
    b.withim(com.shagou.Service..*) 匹配Service包及其子包中所有类所有方法
    c.within(com.shagou.dao.CostDao) 匹配CostDao所有方法
  • Bean名称限定
bean(id值)
    a.bean(costDao) 匹配id = costDaobean对象
    b.bean(*Dao) 匹配所有id值以Dao结尾的bean对象
  • args参数限定表达式
a.args(java.io.Serializable) 匹配方法只有一个参数并且类型符合Serializable的方法 序列化
    public void f1(String s) 
    public void f1(int s) 
    public void f1(int s,int j) 不符合
    session.load(class,Serializable); 
注意:上述表达式可以利用&&,||运算符连接使用
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值