Spring AOP实现原理

一、什么是AOP?

        AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程和 OOP(面向对象编程)类似,也是一种编程思想

二、AOP的作用

        AOP 采取横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入增强代码的可读性和可维护性。简单的说,AOP 的作用就是保证开发者在不修改源代码的前提下,为系统中的业务组件添加某种通用功能。AOP 就是代理模式的典型应用

三、AOP框架  

        目前最流行的 AOP 框架有两个

  • Spring AOP

    • Spring AOP 是基于 AOP 编程模式的一个框架,它能够有效的减少系统间的重复代码,达到松耦合的目的。

    • Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类植入增强的代码。

    • 有两种实现方式:基于接口的 JDK 动态代理和基于继承的 CGLIB 动态代理。

  • AspectJ

    • AspectJ 是一个基于 Java 语言的 AOP 框架,从 Spring 2.0 开始,Spring AOP 引入了对 AspectJ 的支持。AspectJ 扩展了 Java 语言,提供了一个专门的编译器,在编译时提供横向代码的植入。

    • 扩展了Java语言 提供了一门编译器 ,在编译时提供横向的代码织入

  3.1JDK的动态代理    

//目标接口
public interface TargetInterface {
    public void method();
}

//目标类

public class Target implements TargetInterface {
    @Override
    public void method() {
        System.out.println("Target running....");
    }
}

//动态代理

Target target = new Target(); //创建目标对象
//创建代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass()
.getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) 
            throws Throwable {
                System.out.println("前置增强代码...");
                Object invoke = method.invoke(target, args);
                System.out.println("后置增强代码...");
                return invoke;
            }
        }
);

// 测试,当调用接口的任何方法时,代理对象的代码都无序修改
proxy.method();

  3.2cglib 的动态代理 

//目标类
public class Target {
    public void method() {
        System.out.println("Target running....");
    }
}

//动态代理代码

Target target = new Target(); //创建目标对象
Enhancer enhancer = new Enhancer();   //创建增强器
enhancer.setSuperclass(Target.class); //设置父类
enhancer.setCallback(new MethodInterceptor() { //设置回调
    @Override
    public Object intercept(Object o, Method method, Object[] objects, 
    MethodProxy methodProxy) throws Throwable {
        System.out.println("前置代码增强....");
        Object invoke = method.invoke(target, objects);
        System.out.println("后置代码增强....");
        return invoke;
    }
});
Target proxy = (Target) enhancer.create(); //创建代理对象

//调用代理对象的方法测试

//测试,当调用接口的任何方法时,代理对象的代码都无序修改
proxy.method();

  四、AOP的相关术语       

名称说明
Target(目标)指代理的目标对象。
Pointcut(切入点)指要对哪些 Joinpoint 进行拦截,即被拦截的连接点。
Advice(通知)指拦截到 Joinpoint 之后要做的事情,即对切入点增强的内容。
Joinpoint(连接点)指那些被拦截到的点,在 Spring 中,指可以被动态代理拦截目标类的方法。
Weaving(植入)指把增强代码应用到目标上,生成代理对象的过程。
Proxy(代理)指生成的代理对象。
Aspect(切面)切入点和通知的结合。

1.Target 目标类,需要被代理的类,比如:userService

2.Joinpoint 连接点 是指那些可能被拦截的方法 比如:所有的方法

3.Pointcut 切入点 已经被增强的连接点

4.Advice : 通知/增强 :增强代码 (前置通知 、后置通知、返回后通知 、抛出异常通知、环绕通知)

5.Weaving 植入:把增强的方法 应用到目标对象Target 来创建新的代理对象Proxy的过程

6.Proxy :代理类

7.Aspect切面: 是切入点(Pointcut)和通知(Advice)的结合

Pointcut 切入点:

在哪些类上,哪些方法上切入

Advice 通知:

在方法执行的什么时候( 之前 之后 ...)做什么事情(方法)去

Aspect 切面: = 切入点 + 通知

在什么时候 什么地方 做什么增强

植入:Weaving 把切面加入到对象 ,并创建代理的过程

Advice 直译为通知,也有的资料翻译为“增强处理”,共有 5 种类型

通知说明
before(前置通知)通知方法在目标方法调用之前执行
after(后置通知)通知方法在目标方法返回或异常后调用
after-returning(返回后通知)通知方法会在目标方法返回后调用
after-throwing(抛出异常通知)通知方法会在目标方法抛出异常后调用
around(环绕通知)通知方法会将目标方法封装起来

五、使用XML配置开发Spring AOP

自定义类实现 <bean id="xxx" class="xxx.xxx"/>

<aop :config> ​ 自定义切面 ​ <aop:aspect ref="xxx"> ​ ... ​ </aop :aspect> ​ </aop :config>

  • 定义切入点<aop:pointcut> <aop:pointcut> 用来定义一个切入点,当 <aop:pointcut>元素作为 <aop:config> 元素的子元素定义时,表示该切入点是全局切入点,它可被多个切面所共享;当 <aop:pointcut> 元素作为 <aop:aspect> 元素的子元素时,表示该切入点只对当前切面有效。

<aop :config> <aop:pointcut id="point" expression="execution(* com.yjy.service.UserServiceImpl.*(..))"/> </aop :config>

<aop:aspect ref="diyPoint"> <aop:pointcut id="point" expression="execution(* com.yjy.service.UserServiceImpl.*(..))"/>

<!-- 前置通知 -->

<aop:before pointcut-ref="point" method="..."/>

<!-- 后置通知 -->

<aop:after-returning pointcut-ref="point" method="..."/>

<!-- 环绕通知 -->

<aop:around pointcut-ref="point" method="..."/>

<!-- 异常通知 -->

<aop:after-throwing pointcut-ref="point" method="..."/>

<!-- 最终通知 -->

<aop:after pointcut-ref="point" method="..."/> </aop :aspect>

六、使用注解配置开发Spring AOP

在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。

名称说明
@Aspect用于定义一个切面。
@Pointcut用于定义一个切入点。
@Before用于定义前置通知,相当于 BeforeAdvice。
@AfterReturning用于定义后置通知,相当于 AfterReturningAdvice。
@Around用于定义环绕通知,相当于MethodInterceptor。
@AfterThrowing用于定义抛出通知,相当于ThrowAdvice。
@After用于定义最终final通知,不管是否异常,该通知都会执行。
@DeclareParents用于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。
  1. @Before(value = "execution(* com.yjy.spring.impl..(..))")

  2. @After(value = "execution(* com.yjy.spring.impl..(..))")

  3. @AfterReturning(value="execution(* com.yjy.service.impl..(..))")

  4. @AfterThrowing(value="execution(* com.yjy.service.impl..(..))")

  5. @Around(value="execution(* com.yjy.service.impl..(..))")

七、AOP的优点

        AOP 是 Spring 的核心之一,在 Spring 中经常会使用 AOP 来简化编程。在 Spring 框架中使用 AOP 主要有以下优势。

  • 提供声明式企业服务,特别是作为 EJB 声明式服务的替代品。最重要的是,这种服务是声明式事务管理。

  • 允许用户实现自定义切面。在某些不适合用 OOP 编程的场景中,采用 AOP 来补充。

  • 可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时也提高了开发

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值