Spring AOP详解

来源:互联网 发布:修改图片的软件 编辑:程序博客网 时间:2024/06/05 03:37
一、配置方式

1.1、注解
@Aspect 声明该类为一个切面
@Pointcut 切入点
@Before 前置通知
@After 后置通知,方法执行完之后
@AfterReturning 返回通知,成功执行之后
@AfterThrowing 异常通知,抛出异常之后
@Around 环绕通知

1.2、XML

二、切入点表达式(Pointcut Expression)

|——>指示符(designator)
表达式(Expression)——> |——>通配符(wildcard)
|——>运算符(operator)

2.1、表达式符号

2.1.1、指示符
匹配方法:
execution()
匹配注解:
@target()、@args()、@within()、@annotation()
匹配包/类型:
within()
匹配对象:
this()、bean()、target()
匹配参数:
args()

2.1.2、通配符
*:匹配任意数量的字符
+:匹配指定的类及其子类
..:匹配任意数量的子包或参数

2.1.3、运算符
&&||!,匹配其他过滤条件,不多说,同Java

2.2、示例

2.2.1、匹配包/类型
//匹配UserService下所有的方法
@Pointcut("within(org.ljy.service.UserService)")
public void test(){...}

//匹配org.ljy包下的所有类的方法
@Pointcut("within(org.ljy.*)")
public void test(){...}

//匹配org.ljy包及其子包下的所有类的方法
@Pointcut("within(org.ljy..*)")
public void test(){...}

2.2.2、匹配对象
//匹配AOP对象的目标对象为指定类型,在此为DemoDao,this代表的是AOP代理对象
@Pointcut("this(org.ljy.DemoDao)")
public void test(){...}

//匹配实现了IDao接口的目标对象的方法,target为原始对象,即非AOP代理对象
@Pointcut("target(org.ljy.IDao)")
public void test(){...}
//匹配所有以Service结尾的bean里的方法,bean表示以bean的名字匹配
@Pointcut("bean(*Service)")
public void test(){...}

2.2.3、匹配参数
//匹配所有以find开头且只有一个参数类型为Long的方法
@Pointcut("execution(* *..find*(Long))")
public void test(){...}

//匹配所有只有一个参数且类型为Long的方法
@Pointcut("args(Long)")
public void test(){...}

//匹配所有以find开头且第一个参数类型为Long的方法
@Pointcut("execution(* *..find*(Long,..))")
public void test(){...}

//匹配所有第一个参数类型为Long的方法
@Pointcut("args(Long,..)")
public void test(){...}

2.2.4、匹配注解
//匹配方法上有MyAnno注解的方法
@Pointcut("@annotation(MyAnno)")
public void test(){...}

//匹配方法上有MyAnno注解的类里面的所有方法,要求MyAnno的RententionPolicy为CLASS级别
@Pointcut("@within(MyAnno)")
public void test(){...}

//匹配方法上有MyAnno注解的类里面的所有方法,要求MyAnno的RententionPolicy为RUNTIME级别
@Pointcut("@target(MyAnno)")
public void test(){...}

//匹配传入的参数的类上有MyAnno注解的方法
@Pointcut("@args(MyAnno)")
public void test(){...}

2.3、execution()表达式

2.3.1、格式
execution(modifer-pattern? returnType-pattern declaringType-pattern? name-pattern(param-pattern...) throws-pattern?)
翻译一下:
execution(修饰符? 返回类型 包名? 方法名(参数名...) 异常?)
【?表示可省略部分】
如:
//匹配修饰符为public,返回类型为User的org.ljy下以Service结尾的类下的所有方法
execution("public User org.ljy.*Service.*(..) ")

三、Spring AOP的实现原理

|——>代理模式
|——>设计模式——> |
| |——>责任链模式
实现原理——> |
| |——>JDK
|——>实现方式——> |
|——>cglib

3.1、代码的织入

3.1.1、织入时期
  • 编译期(AspectJ)
  • 类加载时(AspectJ 5+)
  • 运行时(Spring AOP)

3.2、代理模式

3.2.1、静态代理
调用被代理的对象(Target)的目标方法的客户端(Caller)通过代理类(Proxy)间接与被代理的对象(Target)进行通讯。
客户端(Caller)通过接口调用目标方法,而代理类(Proxy)收到客户端发来的请求时会把真正的执行交给被代理的类(Target),而代理类可以在目标方法执行前后执行其他的方法。

3.2.2、动态代理
|——>基于接口的(JDK方式)
实现方式——> |
|——>基于继承的(cglib)

  • JDK代理:代理类要实现InvocationHandler接口,且只能基于接口实现代理。
  • Cglib代理:代理类实现MethodInteceptor接口,通过继承方式实现代理,所以无法代理private和final以及static方法。

3.3、Spring对代理模式的选择

  • 如果目标对象实现了接口,则使用JDK代理
  • 如果目标对象没有实现接口,则使用Cglib代理
  • 如果目标对象实现了接口,但强制使用Cglib,则使用Cglib代理

原创粉丝点击