Spring --- AOP相关笔记

概述

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 —> 按照四步骤进行配置


<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">

    
    <bean id="customerService" class="com.itheima.service.impl.CustomerServiceImpl">bean>


    
    
    <bean id="logger" class="com.itheima.utils.Logger">bean>


    
    <aop:config>

        
        <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))">aop:pointcut>

        
        <aop:aspect id="logAdvice" ref="logger">
            
            
            <aop:before method="printLog" pointcut-ref="pt1">aop:before>

            
        aop:aspect>
    aop:config>
beans>

你可能感兴趣的:(spring)