Spring的AOP

AOP模式的理解?

一、介绍

首先我们知道OOP是面向对象编程,主要是实现了顶层向下发送请求,底层向上提供服务的过程! 而所谓面向对象开发是指将实现某个业务的过程分解成由多个对象的行为和属性配合而完成的过程! 那么我们可以知道这个过程肯定是分散而有序的,可以是由一个个由一个或多个对象协作完成的部分组成!

那么AOP在里面充当什么角色呢? spring的AOP主要实现了为单独一个或多个部分提供一些特殊的功能。我们将OOP理解为纵向开发的话,AOP则可以理解为横向开发。为组成纵向的某些流程提供一些切入的服务。

通俗地讲,以面向对象的理念来理解。组成OOP的每个部分又可以看成一个个的对象。AOP使用的场景就是当这些对象有某种权限或者某种需求,但是这些对象没有时间或者自己不乐意去完成的时候。将自己的权限信息交给AOP,AOP作为代理者,代为完成!


二、代理模式

AOP的理念是二十四设计模式中的代理模式,因此学会写AOP框架前,我们需要先理解下代理模式! 第一步部分说到AOP是获取了对象的身份信息,有了权限后才代为完成! 代理模式中的体现更为完善,如下:
代理模式分为静态代理与动态代理?

1.静态代理?

  接口类:

package aop.aop;

/**
 * @Auther: CYQ
 * @Date: 2019/2/17 21:52
 * @Description: 学习的接口
 */
public interface IStudy {
    /**
     * 学习第一步_读书
     * @param bookName
     */
    public void readBooks(String bookName);
}

 接口实现类:

package aop.aop;

/**
 * @Auther: CYQ
 * @Date: 2019/2/17 21:53
 * @Description: 学习的实现类
 */
public class StudyEnglish  implements IStudy {
    /**
     * 读书
     * @param bookName
     */
    @Override
    public void readBooks(String bookName) {
        System.out.println("读:"+bookName+"这本英语书");
    }
}

 代为完成的对象:

package aop.aop;

import sun.nio.cs.ext.ISCII91;

/**
 * @Auther: CYQ
 * @Date: 2019/2/17 21:56
 * @Description:
 */
public class ProxyStudy implements IStudy {
    /**
     * 代理获取Study的信息
     */
    private IStudy  iStudy;//此处为什么用了接口而不是StudyEnglish ,是使用了多态,方便同类型的方法都可以
    public ProxyStudy(IStudy iStudy){
        this.iStudy=iStudy;
    }

    @Override
    public void readBooks(String bookName) {
        System.out.println("-----------专家定制学习内容-----------");
        iStudy.readBooks("根据专家定制的内容,学习:"+bookName);
        System.out.println("-----------专家评估学习效果-------");
    }
}

 如何调用与实现呢?

package aop.aop;

/**
 * @Auther: CYQ
 * @Date: 2019/2/17 22:01
 * @Description:
 */
public class StudyGroup {
    /**
     * 调用
     * @param args
     */
    public  static void main(String[] args){
        ProxyStudy proxyStudy=new ProxyStudy(new StudyEnglish());
        proxyStudy.readBooks("《黑骏马》");
    }
}

  可以非常直观地发现,静态代理模式下,我们可以对方法readBooks()进行重新处理,执行对象也由原来的StduyEnglish转换为    代理学习的对象ProxyStudy。集合Spring中AOP的理解,这就是一个简化版本的AOP? 

 那么Spring的AOP与我们的简易版本AOP有什么区别呢?我们发现spring的AOP可以代理各种对象,而我们的简易版本只能代理我们定义的IStudy类型!那么我们需要进一步优化,引入动态代理模式!

 2.动态代理?

JAVA中存在着反射机制,可以让人根据方法名。然后在jvm内存区中查找整个具体内容,从而获取该方法的使用权限。AOP的本质也是获取到对象的权限后,利用其代为工作。因此为了方便开发,JDK1.3版本后,Java官方提供了一个InvactionHandler。利用此API接口可以实现动态代理。。。。。。

package aop.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Auther: CYQ
 * @Date: 2019/2/18 14:39
 * @Description:  动态代理类
 */
public class StudyCourse implements InvocationHandler {
    /**
     * 被代理的对象信息
     */
    private Object target;

    /**
     * 获取代理对象并内部,进行回调
     * @param object
     * @return
     */
    public Object getProxyClass(Object object){
        this.target=object;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    /**
     * 回调对象内容
     * @param proxy   代理者,如果引入需要类似targer定义好全局变量
     * @param method  被代理类的方法
     * @param args    被代理者传入的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * 此处可以根据需要进行AOP事务的切入
         */
        
        //调用目标方法并获取返回结果
        Object res=method.invoke(this.target,args);

        
        /**
         * 此处可以根据需要进行AOP事务的切入
         */
        return res;
    }
}

  以上为动态代理模式下如何通过反射机制获取代理对象。那么当我们需要为代理对象引入某一个早已经写好的公公模块的时候,应该怎么处理。我们可以将公共模块交给执行代理的执行者。再通过执行者去执行。如下:

package aop.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Auther: CYQ
 * @Date: 2019/2/18 14:39
 * @Description:  动态代理类
 */
public class StudyCourseLogger implements InvocationHandler {
    /**
     * 被代理的对象信息
     */
    private Object target;

    /**
     * 执行代理的人
     */
    private Object proxy;

    /**
     * 获取代理对象并内部,进行回调
     * @param object
     * @return
     */
    public Object getProxyClass(Object object,Object logger){
        this.target=object;
        this.proxy=logger;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    /**
     * 回调对象内容
     * @param proxy   代理者,代为完成的操作者
     * @param method  被代理类的方法
     * @param args    被代理者传入的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * AOP事务切入举例
         * @getDeclaredMehod()  方法区中class文件中的所有方法,并筛选出合适的一个
         */
        Class clazz =proxy.getClass();
        //反射得到操作者的Start方法
        Method  method_proxy = clazz.getDeclaredMethod("执行代理的内部方法名", new Class[]{Method.class});
        method_proxy.invoke(proxy, new Object[]{proxy.getClass()});

        //调用目标方法并获取返回结果
        Object res=method.invoke(this.target,args);


        /**
         * 此处可以根据需要进行AOP事务的切入
         */
        return res;
    }
}

 调用方式如下:

package aop.aop;

import aop.Hello;

/**
 * @Auther: CYQ
 * @Date: 2019/2/17 22:01
 * @Description:
 */
public class StudyGroup {
   /* *//**
     * 调用
     * @param args
     *//*
    public  static void main(String[] args){
        ProxyStudy proxyStudy=new ProxyStudy(new StudyEnglish());
        proxyStudy.readBooks("《黑骏马》");
    }*/

    /**
     * 调用
     * @param args
     */
    public  static void main(String[] args){
        /**
         * 通过反射机制动态获取代理对象信息
         */
        IStudy   strudyEnglish2=(IStudy) new StudyCourse().getProxyClass(new StudyEnglish());
        strudyEnglish2.readBooks("《黑骏马》");

        /**
         * 通过反射机制动态获取代理对象信息,同时hello为代理者,将代理内容给切入到代理者的方法中
         */
        IStudy   strudyEnglish3=(IStudy) new StudyCourseLogger().getProxyClass(new StudyEnglish(),new Hello());
        strudyEnglish3.readBooks("《黑骏马》");
        
    }
}

 由此,我们可以知道AOP的实现如上所述,而在spring中,我们还可以看到各种AOP的引用,如声明式注解的出现。比如日志打印,比如声明式事务。其本质也是AOP的实现。这便是spring的AOP

 

###Spring AOP 的概念 AOP(Aspect-Oriented Programming)即面向切面编程,是一种编程范式,旨在通过分离横切关注点来提高模块化程度。在 Spring 框架中,AOP 被广泛用于实现诸如日志记录、事务管理、安全性等通用功能,这些功能通常与业务逻辑无关但又需要在多个地方重复使用。 Spring AOP 主要是基于 AspectJ 实现的,尽管 AspectJ 是一个独立的 AOP 框架,并不是 Spring 的组成部分,但它通常与 Spring 一起使用以提供更强大的 AOP 功能[^1]。Spring AOP 支持两种方式来定义切面:基于 XML 配置文件的方式和基于注解的方式。 ###Spring AOP 的原理 Spring AOP 使用运行时代理来实现 AOP 功能,这意味着它会在运行时动态生成代理对象。对于实现了接口的类,Spring AOP 默认使用 JDK 动态代理;而对于没有实现接口的类,则会使用 CGLIB 代理[^4]。这种方式允许在不修改原始代码的情况下向程序中添加新的行为。 织入(Weaving)是将增强(advice)应用到目标对象的过程,Spring AOP 在运行时进行织入操作[^3]。当创建了代理对象后,所有对目标对象方法的调用都会被拦截,并且可以插入额外的操作,比如在方法执行前后做一些处理。 ###Spring AOP 的使用教程 要开始使用 Spring AOP,首先需要确保项目中包含了必要的依赖。如果使用 Maven 构建工具,可以在 `pom.xml` 文件中加入如下依赖: ```xml <!-- 引入aop依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 一旦添加了依赖并刷新了 Maven 项目,就可以开始编写切面了。下面是一个简单的例子,展示如何使用注解来定义一个切面: ```java import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Method " + joinPoint.getSignature().getName() + " is called."); } } ``` 在这个示例中,`LoggingAspect` 类被标记为 `@Aspect` 和 `@Component` 注解,这样 Spring 就能识别这是一个切面组件。`@Before` 注解指定了在哪些方法上应用前置通知(before advice),这里的表达式表示匹配 `com.example.service` 包下所有的方法。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值