Java教程

Spring框架-AOP

本文主要是介绍Spring框架-AOP,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

概念

         OOP(Object-Oriented Programming)面向对象编程,允许开发者定义纵向的关系,但并适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。

        AOP(Aspect-Oriented Programming),一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为 “ 切面 ” ( Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。

实现方式

        AOP实现的关键在于 代理模式, AOP 代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以 Spring AOP 为代表。         ( 1) AspectJ 是静态代理的增强,所谓静态代理,就是 AOP 框架会在编译阶段生成 AOP 代理 类,因此也称为编译时增强,他会在编译阶段将 AspectJ( 切面 ) 织入到 Java 字节码中,运行的时候就是增强之后的AOP 对象。          (2 ) Spring AOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次 运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在 特定的切点做了增强处理,并回调原对象的方法。

什么是切面 Aspect

        aspect 由 pointcount 和 advice 组成,切面是通知和切点的结合。 它既包含了横切逻辑的定义, 也包括了连接点的定义 . Spring AOP 就是负责实施切面的框架 , 它将切面所定义的横切逻辑编织到切面所指定的连接点中 . AOP 的工作重心在于如何将增强编织目标对象的连接点上 , 这里包含两个工作 :         1. 如何通过 pointcut 和 advice 定位到特定的 joinpoint 上.         2. 如何在 advice 中编写切面代码 .         可以简单地认为, 使用 @Aspect 注解的类就是切面

 

JDK动态代理和CGLIB动态代理的区别

Spring AOP 中的动态代理主要有两种方式, JDK 动态代理和 CGLIB 动态代理         JDK动态代理只提供接口的代理,不支持类的代理。核心 InvocationHandler 接口和 Proxy类,InvocationHandler 通过 invoke() 方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy 利用 InvocationHandler 动态创建一个符合某一接口的的实例, 生成目标类的代理对象。         如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB ( Code Generation Library ),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP 。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为 fifinal ,那么它是无法使用CGLIB做动态代理的。         静态代理与动态代理区别在于生成AOP 代理对象的时机不同,相对来说 AspectJ的静态代理方式具 有更好的性能,但是 AspectJ 需要特定的编译器进行处理,而 Spring AOP则无需特定的编译器处 理

Spring通知有哪些类型?

        在AOP 术语中,切面的工作被称为通知,实际上是程序执行时要通过 SpringAOP框架触发的代码段。   Spring 切面可以应用 5 种类型的通知:         1. 前置通知( Before ):在目标方法被调用之前调用通知功能;         2. 后置通知( After ):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;         3. 返回通知( After-returning ):在目标方法成功执行之后调用通知;         4. 异常通知( After-throwing ):在目标方法抛出异常后调用通知;         5. 环绕通知( Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

前置通知

准备一个Aspect切面类

public class MyAspects {
    //方法名可以随意
    public void before(JoinPoint joinPoint,String title){
        System.out.println("这是前置增强程序");
    }
}

添加配置

 测试程序

 后置通知

public class MyAspects {
    //方法名可以随意
    public void after(JoinPoint joinPoint,Object returnVal){
        System.out.println("这是后置增强程序");
    }
}

添加配置

         后置通知是在方法返回之后的增强程序,所以可以获取到方法的返回值。

 我们修改业务, 增加返回值

public class MyAspects {
    //方法名可以随意
    public void after(JoinPoint joinPoint,Object returnVal){
        System.out.println("这是后置增强程序");
        System.out.println("被增强方法的返回值为:"+returnVal);
    }
}

 测试程序

 环绕通知, 异常通知, 最终异常

        程序相同, 配置文件中更改方法名即可, 此处略写

使用Advisor的方式进行AOP的配置

前置通知

我们自己写一个类,实现接口MethodBeforeAdvice

public class MyBeforeAdvice implements MethodBeforeAdvice {
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("advisor前置通知");
    }
}

 添加配置

 环绕通知

自己写一个类,实现接口MethodBeforeAdvice

public class MyInterceptor implements MethodInterceptor {
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("{{环绕通知开始}}");
        Object obj = invocation.proceed(); //接受返回值
        System.out.println("{{环绕通知结束}}");
        return obj; // 返回返回值
    }
}

 添加配置

 后置通知, 异常通知, 最终通知, 略

各种通知的执行顺序

        前置通知
        环绕通知开始部分
        [业务部分]
        ///有可能出现异常通知,异常出现,环绕和后置不会再执行
        环绕通知结束
        后置通知
        最终通知(无论是否有异常都必须有后置通知)

这篇关于Spring框架-AOP的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!