Spring AOP

1.Spring AOP是什么?


AOP(面向切面编程) 通过提供另外一种编程结构的思路,补充了OOP(面向对象编程)。OOP中模块化的关键是类,而在AOP中模块化的关键是Aspect切面。切面使关注点[concerns]的模块化(比如事务管理)可以横切多个类和对象。(这些关注点[concern]在AOP文档中通常被称作[crosscutting concerns])。

Spring中的关键组件之一是AOP框架,虽然Spring IOC容器不依赖于AOP,但AOP是对Spring IOC的补充,提供了非常强大的中间件解决方案。

Spring提供了两种简单而又强大的方式来自定义切面:scheme-based 方式、@AspectJ注解风格。这两种方式都提供了[fully typed advice]和AspectJ切入点语言&SpringAOP织入。 

典型应用场景为:事务管理

AspectJ简介

AspectJ 是JAVA面向切面的通用扩展,是AOP编程的完全解决方案,功能强大。来自于Eclipse基金会。

 

2. Spring AOP目标&原理 


 目标:

  • Spring AOP 是纯JAVA实现的,不需要特殊的编译过程。
  • Spring AOP 当前仅支持方法执行上的连接点(建议在Spring Bean的方法执行),没实现对字段拦截的支持。如果你需要可以考虑AspectJ之类的语言。
  • Spring 将AspectJ无缝集成到Spring AOP和IOC,这种集成没有影响到Spring AOP API、 AOP Alliance API。

原理:

Spring AOP 是基于代理的,默认使用JDK动态代理,可以代理任何接口。
Spring AOP 也可以使用CGLIB代理,用于代理类,而不是接口。默认情况下,如果业务对象未实现接口,则使用CGLIB。最佳实践是面向接口编程,在极少数情况下,可以强制使用CGLIB。

 

3 自定义一个切面

3.1 @AspectJ support [推荐方式]


@AspectJ 指将切面声明为带有注解的JAVA Class, @AspectJ风格是由AspectJ项目在AspectJ5版本引入的,Spring通过AspectJ实现的切入点解析&匹配的类库,来支持相同的注解。

【???咋做到的】但是AOP运行时仍然是纯SpringAOP,且并不依赖于ApsectJ编译器或织入器。

启用@AspectJ

@AspectJ 可以通过XML或注解[Java-style configuration]启用,无论哪种方式,你都需要确保引入aspectjweaver.jar (version 1.8 or later)

JAVA注解方式启用@AspectJ

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

}

XML方式启用@AspectJ

<aop:aspectj-autoproxy/>

 

声明一个切面

@AspectJ启用后,你的应用上下文中被@Aspect标注的类,就会自动被Spring检测到并用来配置Spring AOP。下面生命一个啥也没干的切面。

<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
    <!-- configure properties of the aspect here -->
</bean>

 

package org.xyz;
import org.aspectj.lang.annotation.Aspect;

@Aspect
@Component
public class NotVeryUsefulAspect { }

可以像Spring管理其他Bean一样,在配置文件中注册或通过类路径扫描自动检测。但是@Aspect注解不足以在类路径中自动检测。为此需要添加@Component。

声明一个切入点

SpringAOP 只支持在Spring Bean的方法执行进行切入,一个切入点声明包含两部分:切入点标志+切入点表达式。

下面的切入点,定义了一个名为"anyOldTransfer"的切入点,任何方法名为transfer的执行会被切入。

@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature

Spring AOP 的切入点表达式支持以下AspectJ pointcut designators(PCD),以下几个为常用的切入点标识符

execution SpringAOP 主要的切入点标识符,用于匹配方法执行切入点
@within 类具有给定注解,则匹配类内所有方法执行切入点 
@annotation 方法具有给定注解,则匹配方法执行切入点

 

 

 

 

由于Spring AOP 基于代理的性质,因此根据定义不会拦截目标对象内的调用。
对于JDK代理,只能拦截代理上的public接口方法调用。对于CGLIB代理,只能拦截public和protected方法...

 

3.2 scheme-based AOP support 

3.3 Low-Level Spring AOP API

spring提供了一些通知类型,比如Interception around advice,Spring 最基础的切面。

public class DebugInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Before: invocation=[" + invocation + "]");
        Object rval = invocation.proceed();
        System.out.println("Invocation returned");
        return rval;
    }
}

 

 

4. AOP框架对比


 

  来源&背景 织入&编译 功能 学习难易程度
AspectJ

来自于Eclipse基金会

AOP编程的完全解决方案

实际运行前就完成了织入

需要AspectJ编译器

功能强大,性能更好

可编织字段、方法、构造函数

易于学习和使用
SpringAOP 只能作用于Spring容器

只能运行时织入

不需要单独的编译过程

功能不强,较慢

只支持方法级编织

复杂

 

 

 

 

 

 

 

 

5 AOP注意事项 


 

1.  JDK动态代理,只能作用于 public方法,且需要实现接口Interface

2. Cglib代理,只能拦截protected\public方法

3. 由于Spring AOP 基于代理的性质,不会拦截目标对象内的调用

 

参考链接: 

Aspect Oriented Programming with Spring 

 

posted @ 2021-02-08 16:45  大美da美  阅读(160)  评论(0)    收藏  举报