spring——spring的AOP(面向切面编程)

动态代理

                                        

    JDK的动态代理模式:

        场景设计:通过动态代理模式实现事务控制

        动态代理代码:

                                

        JDK的动态代理:

            1.能够实现代码的松耦合,并且能够解决代码重复性的问题。

            2.需要被代理者必须实现接口

            3.动态代理模式只能处理一类业务,如果处理业务不同,需要重新编写动态代理。


    cglib动态代理模式:

        使用cglib动态代理模式,即使被代理者没有实现接口,也可以为其创建代理对象。

        创建代理对象的步骤:

                                       

                                        

                                        

            说明cglib创建的代理对象,底层通过二进制码的形式创建,并且生成的代理对象都是目标对象的子类,并且有无接口都可以生成代理对象

    cglib和jdk的区别:

        jdk创建代理对象的速度较快,cglib创建代理对象的速度较慢

         jdk的动态代理需要实现----InvocationHandler接口



SpringAOP的名称介绍:

    切面Aspect):完成特定功能的类, 能够在目标方法前后做一些额外操作。就是一个切面,

    连接点Joinpoint)客户端调用的某个特定的方法,就是接口中的方法。

    通知Advice):就是切面中的方法(额外的工作),切面类中的方法就是通知。

    切入点Pointcut):(就是一种匹配规则)-----就是在invoke方法中,满足该切入点才能将通知与目标方法结合在一起。在使用目标方法前,进行某些判断(例如if-else ),符合判断中的条件才能将通知与目标方法结合在一起。

    目标对象Target Object):真正调用方法的对象,就是真正要使用的那个方法的对象。就是委托类的对象。


AOP编程:

    场景设计:要使用AOP完成事物控制

    步骤:

        1.导入jar包,导入5jar

                                                                            

        2:定义切面和通知
                                            

        3.编写配置文件

            配置顺序

                                        

            说明:该配置顺序不能跌倒,如果其中某一项不需要配置,直接写下一项

                                    

AOP的执行原理:

    当一个对象执行前先会与切入点表达式进行匹配,如果匹配成功了,就会为这个类创建代理对象(通过动态代理模式创建如果目标对象有接口就使用jdk的动态代理,如果目标对象没有接口则使用cglib生成代理对象),代理对象执行方法时就会执行切面中的通知

切入点表达式:

    1-within() 按类进行匹配控制的粒度比较粗

        Within(包名.类名)

            1.within(cn.service.UserServiceImpl)      只能匹配UserServiceImpl这个类

            2.within(cn.service.*)     匹配当前包下的全部类(一层)

            3.within(cn.service..*)            匹配当前包下的全部子孙包

    2-execution() 控制的粒度较细,能够控制到方法和参数级别

        execution(建议使用)(返回值类型包名.类名.方法名(参数类型))

      (*)所有子类----只能包含一层,只能表示某包下面的所有子类,孙类不行。

      (.*)所有子孙类----包含多层,表示某包下面的所有子孙类。
      (..)任意的----方法类型

    案例:

        例子1<aop:pointcut expression=“execution(int service.UserServiceImpl.add())"   id="txPointcut"/>

                    该切点表达式表示:返回值为int  包名类名serviceUserServiceImpl   方法为add()的匹配规则

        例子2<aop:pointcutexpression="execution(* service.*.add())"   id="txPointcut"/>

                    规则:返回值值任意,包名service下子类的add(),只能包含一层,子孙类不行。

        例子3<aop:pointcut   expression="execution(* service..*.add())"    id="txPointcut"/>

                    规则:方法返回值任意, service包下的所有子孙类的add()

        例子4<aop:pointcut expression="execution(* service..*.add(int,String))"   id="txPointcut"/>

                    规则:返回值的类型任意   service子孙包下的add方法参数类型为int,String

        例子5<aop:pointcut   expression="execution(* service..*.add(..))"   id="txPointcut"/>

                    规则:返回值类型任意   service下的所有子孙类.add方法() (参数任意)


AOP中的通知类型:

       1.前置通知:在执行目标方法以前调用通知   MethodBeforeAdvice 接口
2.后置通知:在执行目标方法以后调用通知 AfterReturningAdvice 接口
3.异常通知:在执行目标方法执行时,出现异常后调用通知 ThrowsAdvice接口方法固定(afterThrowing)
4.环绕通知:在目标方法前后都会调用通知   MethodInterceptor接口
说明:
异常后通知可能告知 异常是什么,但是不能够处理。
环绕通知中可以对异常进行处理,功能比较强大。
5:通知中的参数:参数应该放在第一位,否则报错
环绕通知中的参数使用的是:ProceedingJoinPoint

其他的都使用:joinPoint

                joinPoint.proceed() 作用有两个

                    1.如果有下一个通知,就执行下一个通知,

                    2.如果没有下一个通知则执行目标方法。

6:通知类型的顺序:
<aop:advisor advice-ref="initAdvice" pointcut-ref="txPointcut" order="10"/>
<aop:advisor advice-ref="initAdvice2" pointcut-ref="txPointcut" order="1"/>
通知执行的顺序 可以通过order属性来控制:
前置通知中 数字越小 越先执行   1 先执行 
后置通知中 数字越大 越先执行   10先执行


通知中的参数

    1-除了环绕通知之外,其余的通知全部使用import org.aspectj.lang.JoinPoint;

        而环绕通知使用的是import org.aspectj.lang.ProceedingJoinPoint;

    规定:如果通知中有多个参数,JoinPoint或.ProceedingJoinPoint必须位于参数的第一位否则报错

    2-配置文件中的返回参数应该与通知中的参数一致


后置通知返回值问题:

                                    

    Returning="number" 表示目标方法执行后的返回值

                          

    通知中必须要包含返回值,并且名称相同


异常通知:

                                    

                                


通知的执行规则:

    1.当异常通知执行时,后置通知将不会执行。异常通知和后置通知(after-return)是互斥的。

    2.最终通知无论如何都会被执行。

    3.当目标方法执行时出现异常时,环绕通知的后半部分将不会被执行。

    4.环绕通知遇到后置通知时,如果后置通知想得到返回值,那么环绕通知必须添加return 将返回值返回

    5.当多个环绕通知同时执行时,其执行顺序是嵌套结构

        joinPoint.proceed() 作用有两个

            1.如果有下一个通知,就执行下一个通知,

            2.如果没有下一个通知则执行目标方法。





猜你喜欢

转载自blog.csdn.net/weixin_40663800/article/details/80166257