ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第十三章、Spring动态代理详解

2022-01-26 19:06:07  阅读:143  来源: 互联网

标签:额外 String .. Spring Object 详解 proxy 第十三章 login


在这里插入图片描述

1.额外功能详解

1.MethodBeforeAdvice分析

1. MethodBeforeAdvice接⼝作⽤:额外功能运⾏在原始⽅法执⾏之前,进⾏额外功能操作。
public class Before1 implements MethodBeforeAdvice {
 /*
 作⽤:需要把运⾏在原始⽅法执⾏之前运⾏的额外功能,书写在before⽅法中
 before方法中的三个参数:
 Method: 额外功能所增加给的那个原始⽅法
 login⽅法
 register⽅法
 showOrder⽅法
 Object[]: 额外功能所增加给的那个原始⽅法的参数,和method一一对应。eg:method如果是login(String name,String password)方法,那么Object[]:String name,String password。
 Object: 额外功能所增加给的那个原始对象 UserServiceImpl
 */
 @Override
 public void before(Method method, Object[] args, Object target) throws Throwable {
 System.out.println("-----new method before advice log------");
 }
} 

2. before⽅法的3个参数在实战中,该如何使⽤。
 before⽅法的参数,在实战中,会根据需要进⾏使⽤,不⼀定都会⽤到,也有可能都不⽤。

2.MethodInterceptor(⽅法拦截器)

methodinterceptor接⼝:额外功能可以根据需要运⾏在原始⽅法执⾏ 前、后、或前后都有。

public class Arround implements MethodInterceptor {
    /*
    invoke方法的作用:额外功能书写在invoke方法中
                    额外功能 :运行在原始方法之前、之后、之前之后。
     确定一件事:原始方法怎么运行
     参数:MethodInvocation :额外功能所增加给的那个原始方法。类似before方法的Method
     invocation.proceed() 代表原始方法开始运行。
     额外功能写在invocation.proceed();之前就是在原始方法之前运行额外功能。
     额外功能写在invocation.proceed();之后就是在原始方法之后运行额外功能。
      
      返回值:Object:原始方法的返回值
      通过invocation.proceed()的运行进而获取到原始方法的返回值。
      Object ret = invocation.proceed();
     */

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("额外功能运行在原始方法之前。");
        Object ret = invocation.proceed();
        System.out.println("额外功能运行在原始方法之后。");
        return ret;
    }
}
什么样的额外功能 运⾏在原始⽅法执⾏之前,之后都要添加:事务
    
额外功能运⾏在原始⽅法抛出异常的时候    
public Object invoke(MethodInvocation invocation) throws Throwable {
 Object ret = null;
 try {
 ret = invocation.proceed(); //原始方法抛出异常
 } catch (Throwable throwable) {//捕获异常
 System.out.println("-----原始⽅法抛出异常 执⾏的额外功能 ----");
 throwable.printStackTrace();
 }
 return ret; }

MethodInterceptor影响原始⽅法的返回值

原始⽅法的返回值,直接作为invoke⽅法的返回值返回,MethodInterceptor不会影响原始⽅法的返回值。
      public  boolean login(String name,String password){
        System.out.println("UserServiceImpl.login");
        return  true;
    }
    eg:  public Object invoke(MethodInvocation invocation) throws Throwable { 		
        System.out.println("------log-----");
        Object ret = invocation.proceed();
        return ret; //返回的ret还是true
    }
MethodInterceptor影响原始⽅法的返回值如何做:
Invoke⽅法的返回值,不要直接返回原始⽅法的运⾏结果即可。
public Object invoke(MethodInvocation invocation) throws Throwable {
 System.out.println("------log-----");
 Object ret =invocation.proceed();
 return false; //这里返回给原始方法的返回值是false(一般不改)
}

2.切入点详解

切⼊点决定额外功能加⼊位置(⽅法) 
<aop:pointcut id="pc" expression="execution(* *(..))"/>
exection(* *(..)) ---> 匹配了所有⽅法

1. execution() 切⼊点函数
2. * *(..) 切⼊点表达式

2.1 切入点表达式

1.方法切入点表达式

在这里插入图片描述

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

eg:定义login⽅法作为切⼊点
* login(..)

定义register register作为切⼊点
* register(..)

* login(String,String)

eg:定义login⽅法且login⽅法有两个字符串类型的参数 作为切⼊点
##注意:⾮java.lang 包中的类型,必须要写全限定名
* register(com.baizhiedu.proxy.User)

 ..可以和具体的参数类型连⽤
* login(String,..) 可以匹配第一个参数是String,后面的参数没有要求。
可以匹配如下方法:
login(String),login(String,String),login(String,com.baizhiedu.proxy.User)

上面所讲解的方法切入点表达式不精准。
eg:在两个包(a,b)中有相同方法名和参数列表的方法login,而我只想要匹配其中一个包的方法。login(String,String)会把两个包的login方法都匹配到。

2.2精准⽅法切⼊点限定

在这里插入图片描述

修饰符 返回值 	包.类.⽅法(参数)
    * 			com.baizhiedu.proxy.UserServiceImpl.login(..)
    * 			com.baizhiedu.proxy.UserServiceImpl.login(String,String)

2.3 类切⼊点

在这里插入图片描述

指定特定类作为切⼊点(额外功能加⼊的位置),那么这个类中的所有⽅法,都会加上对应的额外功能
语法1:
    #类中的所有⽅法加⼊了额外功能
* com.baizhiedu.proxy.UserServiceImpl.*(..)
    
语法2:
    #忽略包
1. 类只存在⼀级包 
com.UserServiceImpl(此时类UserServiceImpl直接在com包下)
* *.UserServiceImpl.*(..)
2. 类存在多级包 
com.baizhiedu.proxy.UserServiceImpl(此时类UserServiceImpl在com.baizhiedu.proxy多级包下)
* *..UserServiceImpl.*(..)    --- 多加一个点

2.4包切入点表达式(实战更多)

指定包作为额外功能加⼊的位置,那么包中的所有在配置文件中创建对象的类 以及类中的所有⽅法都会加⼊额外的功能。
语法1:
    #切⼊点包中的所有类,必须在proxy包中,不能在proxy包的⼦包中
* com.baizhiedu.proxy.*.*(..)
语法2:
    #切⼊点当前包及其⼦包都⽣效(在当前包后面多加一个点)
* com.baizhiedu.proxy..*.*(..)

2.5切⼊点函数

切⼊点函数:⽤于执⾏切⼊点表达式

1.execution

1. 最为重要的切⼊点函数,功能最全。
2. 执⾏⽅法切⼊点表达式、类切⼊点表达式、包切⼊点表达式
3. 弊端:execution执⾏切⼊点表达式书写麻烦
 eg:execution(* com.baizhiedu.proxy..*.*(..))
 
4. 注意:其他的切⼊点函数 简化了execution书写复杂度,功能上完全⼀致

2.切入点函数:args

1. 作⽤:主要⽤于函数(⽅法) 参数的匹配
2. 切⼊点:⽅法参数必须得是2个字符串类型的参数:不管你是哪个包下哪个类下的 只关心参数
  		 execution(* *(String,String)) == args(String,String)

3.切入点函数:within

	# 作⽤:主要⽤于进⾏类、包切⼊点表达式的匹配 (把方法和参数取消了)
切⼊点:UserServiceImpl这个类:
1.  execution(* *..UserServiceImpl.*(..)) == within(*..UserServiceImpl)
切⼊点:proxy这个包:
2. execution(* com.baizhiedu.proxy..*.*(..)) ==  within(com.baizhiedu.proxy..* )

4.@annotation

作⽤:为具有特殊注解的⽅法加⼊额外功能  
<aop:pointcut id="pc" expression="@annotation(com.baizhiedu.Log)"/>

在这里插入图片描述

2.6切⼊点函数的逻辑运算

指的是 整合多个切⼊点函数⼀起配合⼯作,进⽽完成更为复杂的需求

and:与操作
案例:login方法同时 参数是2个字符串的方法
1. execution(* login(String,String))  ==
2. execution(* login(..)) and args(String,String)
    3.注意:与操作不能⽤于同种类型的切⼊点函数;
    	eg:execution(* login(..)) and execution(* register(..))
    		这种写法错误,因为不存在既叫login又叫register的方法。

or:或操作
案例:register⽅法 和 login⽅法作为切⼊点
    execution(* login(..)) or execution(* register(..))

标签:额外,String,..,Spring,Object,详解,proxy,第十三章,login
来源: https://blog.csdn.net/dougongzi/article/details/122699997

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有