Spring中AOP

动态代理

特点: 
    字节码随用随创建,随用随加载
作用:
    不修改源码的基础上对方法增强
分类:
    1. 基于接口的动态代理
        涉及的类:
            Proxy
        提供者:
            jdk官方
        如何创建代理对象:
            使用Proxy类中的newProxyInstance方法
        创建代理对象的要求:
            被代理的类至少实现一个接口,如果没有则不能使用
        newProxyInstance方法的参数:
            ClassLoader:类加载器
                它是用于加载代理对象字节码的,和被代理对象使用相同的类加载器,固定写法
            Class[]:字节码数组
                它是用于让代理对象和被代理对象有相同的方法,固定写法
            InvocationHandler:用于提供增强的代码
                它是用于让我们写如何代理,我们一般都是写一个该接口的实现类,通常是一个匿名内部类(不是必须的)
                此接口的实现类都是谁用谁写

        *存在的问题:当我们的类没有实现任何的接口的时候是不可以使用的

        代理对象执行方法,其实就是代替被代理对象执行方法

        被代理对象实现接口
        生成代理对象
        代理对象.被代理对象的方法

    2. 基于子类的动态代理(cglib)

        涉及的类:
            Enhancer
        提供者:
            第三方cglib库
        如何创建代理对象:
            使用Enhancer类中的create方法
        创建代理对象的要求:
            被代理的类不是最终类,不能被final修饰
        create方法的参数:
            Class:字节码
                它是用于指定被代理对象的字节码
            Callback:用于提供增强的代码
                它是用于让我们写如何代理,我们一般都是写一个该接口的实现类,通常是一个匿名内部类(不是必须的)
                此接口的实现类都是谁用谁写
                我们一般写的都是该接口的子接口实现类:MethodIntercepor

Spring中的AOP

概述:
    AOP:全称是 Aspect Oriented Programming 即:面向切面编程。    
    简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的
    基础上,对我们的已有方法进行增强
作用以及优势:
    作用:
        在程序运行期间,不修改源码对已有方法进行增强。
    优势:
        减少重复代码
        提高开发效率
        维护方便
实现方式:
    使用动态代理技术
AOP相关术语:

    连接点:
        目标对象的所有方法(所有的切入点都是连接点)
    切入点:
        被增强的都是切入点
    增强/通知:
        关于增强的代码块(可以是抽取出来的类)
    引介:
        是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。
    Target:
        被代理的对象
    织入:
        是指把增强应用到目标对象来创建新的代理对象的过程。
        spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
    代理(Proxy):
        一个类被AOP织入增强后,产生的结果代理类

    切面:
        切入点与通知的结合

Spring在AOP开发中代理方式的选择

proxy-target-class
    默认false: 自动选择  
    true: 使用cglib代理

1. 基于XML的
    <aop:config proxy-target-class="true">
    .....
    </aop:config>

2. 基于注解
     <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

Spring中基于XML的AOP的配置

1. 把通知bean交给Spring来管理
2. 使用aop:config标签表明开始AOP的配置
3. 使用aop:aspect标签表明开始配置切面
    id属性:给切面提供一个唯一标识
    ref属性:是指定通知类bean的id
4. 在aop:aspect标签的内部使用对用的标签来配置通知的类型
    前置通知:    aop:before(表示配置前置通知)
            method属性:用于指定类中哪个方法是前置通知
            pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层的哪些方法增强
    切入点表达式的写法:
        关键字: execution(表达式)
        表达式:
            访问修饰符  返回值  包名.包名...类名.方法名(参数列表)
        标准表达式的写法:
            execution(public void com.qin.service.impl.AccountServiceImpl.xxx(..))
        访问修饰符可以省略
            void com.itheima.service.impl.AccountServiceImpl.saveAccount()
        返回值可以使用通配符,表示任意返回值
            * com.itheima.service.impl.AccountServiceImpl.saveAccount()
        包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.
            * *.*.*.*.AccountServiceImpl.saveAccount())
        包名可以使用..表示当前包及其子包
            * *..AccountServiceImpl.saveAccount()
        类名和方法名都可以使用*来实现通配
            * *..*.*()
        参数列表:
            可以直接写数据类型:
            基本类型直接写名称           int
            引用类型写包名.类名的方式   java.lang.String
            可以使用通配符表示任意类型,但是必须有参数
            可以使用..表示有无参数均可,有参数可以是任意类型
        全通配写法:
            * *..*.*(..)

        实际开发中切入点表达式的通常写法:
            切到业务层实现类下的所有方法
            * com.itheima.service.impl.*.*(..)


5. 例
    <!-- 配置目标类-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>


    <!-- 配置通知类 -->
    <bean id="logger" class="com.itheima.utils.Logger"></bean>

    <!--配置AOP-->
    <aop:config>
    <!-- 配置切入点表达式 id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容
          此标签写在aop:aspect标签内部只能当前切面使用。
          它还可以写在aop:aspect外面,此时就变成了所有切面可用
      -->
    <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>



    <!--配置切面 -->
    <aop:aspect id="logAdvice" ref="logger">
        <!-- 配置前置通知:在切入点方法执行之前执行-->
        <aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>

        <!-- 配置后置通知:在切入点方法正常执行之后值。它和异常通知永远只能执行一个-->
        <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"
                 returning="val"></aop:after-returning>

        <!-- 配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个-->
        <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1" throwing="ex"></aop:after-throwing>

        <!-- 配置最终通知:无论切入点方法是否正常执行它都会在其后面执行-->
        <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>

        <!-- 配置环绕通知 -->
        <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
    </aop:aspect>
    </aop:config>

 

Spring中基于注解的AOP

1. 目标对象
    即被代理的对象
        如:业务层的AccountServiceImpl
2. 通知对象
    即散落在其他类中可以抽取成共性的代码块,可以提取成为一个类(比如日志记录,代码性能监控)
3. 在核心配置中开启对AOP的支持
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4. 使用注解在通知上配置切面
    4.0 表示当前类是一个切面类
        @Aspect
    4.1 配置切点
        @Pointcut("execution(* com.itheima.service.impl.*.update(..))")
            private void pt1(){}
        @Pointcut("execution(* com.itheima.service.impl.*.save(..))")
            private void pt2(){}
    4.3 在方法上配置注解
        @Before        前置通知
        @After            最终通知
        @AfterReturning    后置通知
        @AfterThrowing    异常通知
        @Around        环绕通知
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值