4. AOP

发布时间:2023年12月30日

1 AOP能解决什么问题

1.1 提出问题

1.1.1 情景:数学计算器
1.1.1.1 要求

①执行加减乘除运算
②日志:在程序执行期间追踪正在发生的活动
在这里插入图片描述

ArithmeticCalculator.java

public interface ArithmeticCalculator {
    double add(double a, double b);

    double sub(double a, double b);

    double mul(double a, double b);

    double div(double a, double b);
}

ArithmeticCalculatorImpl.java

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public double add(double a, double b) {
        return a + b;
    }

    @Override
    public double sub(double a, double b) {
        return a - b;
    }

    @Override
    public double mul(double a, double b) {
        return a * b;
    }

    @Override
    public double div(double a, double b) {
        return a / b;
    }
}
1.1.1.2 常规实现

ArithmeticCalculatorImpl.java

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public double add(double a, double b) {
        System.out.println("The method add begins with [" + a + ", " + b + "]");
        double result = a + b;
        System.out.println("The method add ends with " + result);
        return result;
    }

    @Override
    public double sub(double a, double b) {
        System.out.println("The method sub begins with [" + a + ", " + b + "]");
        double result = a - b;
        System.out.println("The method sub ends with " + result);
        return result;
    }

    @Override
    public double mul(double a, double b) {
        System.out.println("The method sub begins with [" + a + ", " + b + "]");
        double result = a * b;
        System.out.println("The method sub ends with " + result);
        return result;
    }

    @Override
    public double div(double a, double b) {
        System.out.println("The method sub begins with [" + a + ", " + b + "]");
        double result = a / b;
        System.out.println("The method sub ends with " + result);
        return result;
    }
}
1.1.1.3 问题

①代码混乱:越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀。每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点。
②代码分散: 以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块(方法)里多次重复相同的日志代码。如果日志需求发生变化,必须修改所有模块。

1.2 动态代理

1.2.1 动态代理的原理

代理设计模式的原理:使用一个代理将原本对象包装起来,然后用该代理对象”取代”原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
在这里插入图片描述

1.2.2 动态代理的方式
  • 基于接口实现动态代理: JDK动态代理
  • 基于继承实现动态代理: Cglib、Javassist动态代理

1.3 数学计算器的改进(JDK动态代理)

1.3.1 日志处理器

CalculatorLoggingHandler.java

public class CalculatorLoggingHandler implements InvocationHandler {
    private Object target;

    public CalculatorLoggingHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("The method " + method.getName() + "() begins with " + Arrays.toString(args));
        Object result = method.invoke(target, args);
        System.out.println("The method " + method.getName() + "() ends with " + result);
        return result;
    }

    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new CalculatorLoggingHandler(target));
    }
}

1.3.2 测试代码

Main.java

public class Main {
    public static void main(String[] args) {
        ArithmeticCalculatorImpl arithmeticCalculator = new ArithmeticCalculatorImpl();

        ArithmeticCalculator proxy = (ArithmeticCalculator) CalculatorLoggingHandler.createProxy(arithmeticCalculator);

        System.out.println(proxy.add(12, 13));
    }
}

1.3.3 测试结果

The method add() begins with [12.0, 13.0]
The method add() ends with 25.0
25.0

文章来源:https://blog.csdn.net/muLanlh/article/details/135268579
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。