Spring --- AOP相关笔记

本文介绍了AOP(Aspect Oriented Programming),其可隔离业务逻辑各部分,降低耦合性,提高程序可重用性和开发效率。阐述了AOP的作用、优势、原理及相关术语,如连接点、切入点等。还说明了在Spring中根据目标类是否实现接口选择代理方式,并讲解了使用xml配置AOP的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

AOP:Aspect Oriented Programming
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合性降低,提高程序的可重用性的,同时提高开发效率。
AOP作用及优势
作用:在程序运行期间,不修改源码对已有方法进行增强
优势:减少重复代码,提高开发效率,维护方便
原理:采用动态代理的方式(基于接口的动态代理和基于子类的动态代理)

/**
 * 一个演员
 */
public class Actor implements IActor {
    /**
     * 基本的表演
     *
     * @param money
     */
    public void basicAct(float money) {
        System.out.println("拿到钱,开始基本的表演:" + money);
    }

    /**
     * 危险的表演
     *
     * @param money
     */
    public void dangerAct(float money) {
        System.out.println("拿到钱,开始危险的表演:" + money);
    }
}
------------------
基于接口的动态代理
/**
 * 模拟一个剧组
 */
public class Client {
    public static void main(String[] args) {
        final Actor actor = new Actor();
//        actor.basicAct(100f);
//        actor.dangerAct(500f);
        /**
         * 动态代理:
         *      作用:不改变源码的基础上,对己方已有的方法增强。(它是AOP思想的实现技术)
         *      分类:
         *          基于接口的动态代理:
         *                  要求:被代理类最少实现一个接口
         *                  提供者:JDk官方
         *                  涉及的类:Proxy
         *              创建代理对象的方法:newProxyInstance(ClassLoader,Class[],InvocationHandler)
         *                  参数含义:
         *                ClassLoader:类加载器。和被代理对象使用相同的类加载器。一般都是固定写法。
         *                    Class[]:字节码数组。被代理类实现的接口。(要求被代理对象和代理对象具有相同的行为)。一般都是固定写法。
         *          InvocationHandler:它是一个接口,就是用于我们提供增强代码的。我们一般都是写一个该接口的实现类。实现类可以是匿名内部类。
         *                                        它的含义是:如何代理。此处的代码只能是谁用谁提供
         *                                        策略模式:
         *                                            使用要求:数据已经有了
         *                                                     目的明确
         *                                                     达成目标的过程就是策略。
         *                                            在dbutils中的ResultSetHandler就是策略模式的具体应用
         *           基于子类的动态代理
         */
        IActor proxyActor = (IActor) Proxy.newProxyInstance(actor.getClass().getClassLoader(),
                actor.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     *
                     * 执行被代理对象的任何方法都会经过该方法,该方法有拦截的功能
                     * 方法的参数:
                     *      Object proxy:代理对象的引用。不一定每次都会有
                     *      Method method:当前执行的方法
                     *      Object[] args:当前执行方法所需的参数
                     * 返回值:
                     *      当前执行方法的返回值
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object rtValue = null;
                        //1.取出执行方法中的参数
                        Float money = (Float)args[0];
                        //2.判断当前执行的是什么方法
                        if("basicAct".equals(method.getName())){
                            //基本演出
                            if(money > 10000){
                                //执行方法(开始表演)
                                rtValue = method.invoke(actor, money/2);
                            }
                        }
                        if("dangerAct".equals(method.getName())){
                            //危险演出
                            if(money > 50000){
                                //执行方法
                                rtValue = method.invoke(actor, money/2);
                            }
                        }

                        return rtValue;
                    }

                });
        proxyActor.basicAct(20000);
        proxyActor.dangerAct(60000);
    }
}

-------------
基于子类的动态代理
/**
 * 模拟一个剧组
 */
public class Client {
    public static void main(String[] args) {
        final Actor actor = new Actor();
//        actor.basicAct(100f);
//        actor.dangerAct(500f);
        /* *
         * 动态代理:
         *      作用:不改变源码的基础上,对己方已有的方法增强。(它是AOP思想的实现技术)
         *      分类:
         *              基于接口的动态代理:
         *
         *              基于子类的动态代理:
         *                  要求:被代理类不能是最终类。不能被final修饰
         *                  提供者:第三方CGLIB
         *                  涉及的类:Enhancer
         *                  创建代理对象的方法:creat(Class,Callback);
         *                  参数的含义:
         *                      Class:被代理对象的字节码
         *                      Callback:如何代理。他和InvocationHandler的作用是一样的他也是一个接口,我们一般使用该接口的子接口MethodInterceptor
         *                              在使用时我们也是创建该接口的匿名内部类。
         */
        Actor cglibAct = (Actor) Enhancer.create(actor.getClass(), new MethodInterceptor() {
            /**
             * 执行被代理对象的任何方法,都会经过该方法。他和基于接口动态代理的invoke方法方法的作用是一模一样的。
             * 方法参数:
             *      前面三个和invoke方法的参数含义都一样。
             *      MethodProxy methodProxy:当前执行方法的代理对象。一般不用。
             */
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object rtValue = null;
                //1.取出执行方法中的参数
                Float money = (Float) args[0];
                //2.判断当前执行的是什么方法
                if ("basicAct".equals(method.getName())) {
                    //基本演出
                    if (money > 10000) {
                        //执行方法(开始表演)
                        rtValue = method.invoke(actor, money / 2);
                    }
                }
                if ("dangerAct".equals(method.getName())) {
                    //危险演出
                    if (money > 50000) {
                        //执行方法
                        rtValue = method.invoke(actor, money / 2);
                    }
                }

                return rtValue;
            }
        });

        cglibAct.basicAct(20000);
        cglibAct.dangerAct(60000);
    }
}

**关于代理的选择 : ** 在spring中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式
**AOP相关术语 : **

JoinPoint(连接点):所谓连接点就是指那些被拦截到的点。在spring中,这些点指的就是方法,因为spring只支持方法类型的连接点。
Pointcut(切入点):所谓切入点就是指我们要对那些JoinPoint进行拦截的定义。(被增强的就是切入点)
Advice(通知/增强):所谓通知是指拦截到JoinPoint之后所要做的事情就是通知。通知类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期间为类动态地添加一些方法或field。
Target(目标对象):代理目标对象。
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而aspectJ采用编译期织入和类装载期织入。
Proxy(代理):一个类AOP织入增强后,就产生一个结果代理类
Aspect(切面):是切入点和通知(引介)的结合。

使用xml配置AOP

导入坐标 —> 配置好IoC —> 按照四步骤进行配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置service -->
    <bean id="customerService" class="com.itheima.service.impl.CustomerServiceImpl"></bean>


    <!-- 基于xml的aop配置步骤 : 要想使用spring的aop,必须向导入aop的jar包-->
    <!-- 第一步:把通知bean交给spring来管理 -->
    <bean id="logger" class="com.itheima.utils.Logger"></bean>


    <!-- 第二步:导入AOP名称空间,并且使用 aop:config 标签 开始aop的配置 -->
    <aop:config>

        <!-- 定义通用切入点表达式,如果写在aop:aspect标签外部,则表示所有切面可用 -->
        <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>

        <!-- 第三步:使用 aop:aspect 标签 配置切面  id属性:用于给切面提供一个唯一标识。ref属性:用于应用通知的Bean的id-->
        <aop:aspect id="logAdvice" ref="logger">
            <!-- 第四步:在aspect标签内部 配置通知的类型,指定增强的方法何时执行。
                    method属性:用于指定增强的方法名称 。
                    pointcut属性:用于指定切入点表达式-->
            <!-- 切入点表达式:
            关键字:execution(表达式)
            表达式写法:
            访问修饰符 返回值 包名.包名..类名.方法名(参数列表)
            全匹配方式:
                public void com.itheima1515.service.impl.CustomerServiceImpl.saveCustomer()
            访问修饰符可以省略
                void com.itheima1515.service.impl.CustomerServiceImpl.saveCustomer()
            返回值可以使用通配符,表示任意返回值。通配符是*
                * com.itheima1515.service.impl.CustomerServiceImpl.saveCustomer()
            包名可以使用通配符,表示任意符,但是,有几个包就需要写几个*
                * *.*.*.*.CustomerServiceImpl.saveCustomer()
            包名可以使用..表示当前包及其子包
                * com..CustomerServiceImpl.saveCustomer()
            类名和方法名都可以使用通配符
                * com..*.*()
            参数类别可以使用基本类型,表示参数类型
            基本类型直接写类型名称:int
            引用类型必须是包名.类名。java.lang.Integer
            参数列表可以使用通配符,表示任意参数类型,但是必须有参
                * com..*.*(*)
            参数列表可以使用..表示有无参数均可,有参数可以是任意类型
                * com..*.*(..)
            全通配方式:
                * *..*.*(..)
            实际开发中,我们都是对业务层方法进行增强:
            所以写法:* com.itheima1515.service.impl.*.*(..)


            -->
            <aop:before method="printLog" pointcut-ref="pt1"></aop:before>

            <!-- 定义通用切入点表达式:如果写在了aop:aspect标签内部,则表示只有当前切面可用
            <aop:pointcut id="pt1" expression="execution(* com.itheima1515.service.impl.*.*(..))"></aop:pointcut>
            -->
        </aop:aspect>
    </aop:config>
</beans>
1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、年龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值