Spring动态代理详解、AOP编程 打卡第七天

第三章、Spring动态代理详解

1.额外功能的详解

1.MethodBeforeAdvice分析

1.MethodBeforeAdvice接口作用:额外功能运行在原始功能执行之前,进行额外功能操作

public class Before implements MethodBeforeAdvice {
    /**
     * 作用: 把需要运行在原始方法执行之前运行的额外功能, 书写在 before 方法中
     *
     * Method: 额外功能所增加给的那个原始方法
     *                          login
     *                          register
     *                          --------
     *                          showOrder
     *
     * Object[]:  额外功能所增加给的那个原始方法的参数
     *                          String name,String password
     *                          User
     *                          --------
     *
     * Object: 额外功能所增加给的那个原始对象
     *                          UserServiceImpl
     *                          ---------------
     *                          OrderServiceImpl
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("---new method before advice log---");
    }
}

2.before方法中的3个参数在实战中,该如何使用

before方法的参数,在实战中,会根据需求进行使用,不一定都会用到,也有可能都用不到

孙哥:”我用了 15 年 Spring 一次都没有用到过这个。"

3.MethodInterceptor(方法拦截器)

MethodInterceptor接口:额外功能可以根据需要运行在原始方法执行的 前 后 前后

  • 参数:MethodInvocation:额外功能所增加给的那个原始方法 (login, register)
  • 返回值:Object:原始方法的返回值 (没有就返回 null)
  • invocation.proceed():原始方法运行

额外功能运行原始方法执行之前

public class Around implements MethodInterceptor {
    /*
    invoke方法的作用:额外功能书写invoke
     */
    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        System.out.println("---------log------");
        Object ret = Invocation.proceed();
        return ret;
    }
}

额外功能运行原始方法执行之后

public class Around implements MethodInterceptor {
    /*
    invoke方法的作用:额外功能书写invoke
     */
    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        Object ret = Invocation.proceed();
        System.out.println("---------log------");
        return ret;
    }
}

额外功能运行原始方法执行之前 之后

什么样的额外功能 运行在原始方法执行之前 之后
事务!
public class Around implements MethodInterceptor {
    /*
    invoke方法的作用:额外功能书写invoke
     */
    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        System.out.println("---------log------");
        Object ret = Invocation.proceed();
        System.out.println("---------log------");
        return ret;
    }
}

额外功能运行在原始方法抛出异常的时候

public class Around implements MethodInterceptor {
    /*
    invoke方法的作用:额外功能书写invoke
     */
    @Override
    public Object invoke(MethodInvocation Invocation) throws Throwable {
        Object ret = null;
        try {
            ret = Invocation.proceed();
        } catch (Throwable e) {
            System.out.println("---------原始方法抛出异常 执行的额外功能---------");
            e.printStackTrace();
        }
        return ret;
    }
}

MethInterceptor影响原始方法的返回值

原始方法的返回值,直接作为invoke方法的返回值返回,MethodInterceptor不会影响原始方法的返回值

MethodInterceptor影响原始方法的返回值

invok方法的返回值,不要返回原始方法的运行结果即可
public class Around implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("---log---");
        Object ret = methodInvocation.proceed();
        return false;
    }
}

2.切入点详解

切入点决定额外功能加入的位置(方法)

<aop:pointcut id="pc" expression="execution(* *(..))"/>
expression="execution(* *(..))--->匹配所有方法  

<aop:pointcut id="pc" expression="execution(* *(..))"/>
expression="execution(* *(..))--->匹配所有方法  

2.1切入点表达式

1.方法切入点表达式

1.* *(..)--->匹配所有方法

定义一个方法
public void add(int i, int j)
   *               *      (..)

* * (..)    --> 所有方法

*  --->  修饰符 返回值
*  --->  方法名
() --->  参数表
.. --->  对于参数没有要求 (参数有没有,参数有⼏个都行,参数是什么类型的都行)

定义login方法作为切入点

<!-- 定义login作为切入点 -->
<aop:pointcut id="pc" expression="execution(* login (..))"/>

<!-- 定义register作为切入点 -->
<aop:pointcut id="pc" expression="execution(* register (..))"/>

定义login方法且login方法有两字符串类型参数作为切入点

<aop:pointcut id="pc" expression="execution(* login (String,String))"/><

<!-- ⾮ java.lang 包中的类型, 必须要写全限定名 -->
<aop:pointcut id="pc" expression="execution(* register (com.yusael.proxy.User))"/>

<!--  ..可以和具体的参数类型连用 -->
<aop:pointcut id="pc" expression="execution(* login(String, ..))"/>
<!-- === login(String), login(String,String), login(String,com.baizhi.edu.proxy.User) -->

精准方法切入点限定

修饰符 返回值 包。类。方法(参数)

<aop:pointcut id="pc" expression="execution(* com.yusael.proxy.UserServiceImpl.login(..))"/>

<aop:pointcut id="pc" expression="execution(* com.yusael.proxy.UserServiceImpl.login(String, String))"/>

2.类切入点

指定特定的类作为切入点(额外功能加入的位置),自然这个类中的所有方法,都会加入对应的额外功能

语法1

类中所有的方法都加入了额外功能

* com.liulei.proxy.UserServiceImpl.*(..)

语法2

#忽略包
1.类只存在一级包    com.UserServiceImpl
<aop:pointcut id="pc" expression="execution(* *.UserServiceImpl.*(..))"/>

2.类存在多级包 com.liulei.proxy.UserServiceImpl
<aop:pointcut id="pc" expression="execution(* *..UserServiceImpl.*(..))"/>

3.包切入点表达式(更具有实战价值)

1.指定包作为额外功能加入的位置,自然包中的所有类以及方法都会加入额外功能

语法1

#切入点包中的所有类,必须在proxy包中,不能在proxy包的子包中。
<aop:pointcut id="pc" expression="execution(* com.liulei.proxy.*.*(..))"/>

语法2

# 切入点当前包及其⼦包都生效
<aop:pointcut id="pc" expression="execution(* com.liulei.proxy..*.*(..))"/>

2.2 切入点函数

切入点函数:用于执行切入点表达式

1.execution

1.最为重要的切入点函数

2.执行了方法切入点表达式,类切入点表达式,包切入点表达式

弊端:execution执行切入点表达式,书写麻烦

注意:其他切入点的函数,简化execution书写的复杂度,功能一样

2.args

作用:主要用于函数(方法)参数的匹配

切入点:方法参数必须是2个字符串类型的参数

# 使用 execution
<aop:pointcut id="pc" expression="execution(* *(String, String))"/>

# 使用 args<aop:pointcut id="pc" expression="args(String, String)"/>

3.within

作用:主要用于进行类,包切入点的表达式的匹配

切入点: UserServiceImpl 这个类

# 使用 execution
<aop:pointcut id="pc" expression="expression(* *..UserServiceImpl.*(..))"/>

# 使用 within
<aop:pointcut id="pc" expression="within(*..UserServiceImpl)"/>

切入点: com.yusael.proxy 这个包

# 使用 execution
<aop:pointcut id="pc" expression="execution(* com.liulei.proxy..*.*(..)"/>

# 使用 within
<aop:pointcut id="pc" expression="within(com.liulei.proxy..*)"/>

4.@annotation

作用:为具有特殊注解的方法加入额外功能

创建注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}

然后我们要为使用Log注解的方法提供额外功能

<aop:pointcut id="pc" expression="@annotation(com.liulei.Log)"/>

5.切入点函数的逻辑运算

指的是 整合多个切入点函数一起配合工作,进而完成更为复杂的需求

and与操作

5.切入点函数的逻辑运算

指的是 整合多个切入点函数一起配合工作,进而完成更为复杂的需求

and与操作

注意:与操作不能用于通知类型的切入点函数

案例:注意:与操作不同⽤于同种类型的切⼊点函数

以下这个是错误的, 因为不存在同时叫 login 和 register 的方法

<aop:pointcut id="pc" expression="execution(* login(..)) and execution(* register(..))"/>

or或操作

案例: 方法名叫 register 或 login 的⽅法作为切⼊点
<aop:pointcut id="pc" expression="execution(* login(..)) or execution(* register(..))"/>

第四章、AOP编程

1. AOP概念

AOP(Aspect Oriented Programing) 面向切面编程 Spring动态代理开发

以切面为基本单位的开发,通过切面间的彼此协调,相互调用,完成程序的创建

切面 = 切入点 + 额外功能/

OOP(Object Oriented Programing) 面向对象编程 Java

以对象为基本单位的程序开发,通过对象间得彼此协同,相互调用,完成程序构建

POP(Producer Oriented Programing)面向过程(方法,函数)编程

以过程为基本单位的程序开发,通过过程间彼此协调,相互调用,完成程序构建

AOP概念

本质就是Spring的动态代理开发,通过代理类为原始类增加额外功能

好处:有利于原始类的维护

注意:AOP编程不可能取代OOP,是OOP编程的补充

2. AOP编程的开发步骤

1.原始对象

2.额外功能(MethodInterceptor)

3.切入点

4.组装切面(额外功能+切入点)

3.切面的名词解释

切面 = 切入点 + 额外功能

几何学

面 = 点+ 相同的性质

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值