为什么要使用AOP

为什么要使用AOP

每个技术的诞生都是为了解决问题的,而AOP是为了解决什么问题的呢?

发现问题 
假设我们要实现一个计算器功能,要求 
- 能够实现基本的加减乘除计算功能 
- 要求实现日志功能 
实现上面的需求比较直接简单的方法是:在每个计算功能核心代码中都写入日志输出处理。

  • 写一个计算器接口
package com.spring.proxy;

public interface Calculator {

    int add(int i,int j);
    int sub(int i,int j);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 实现类:
package com.spring.proxy;

public class CalculatorImpl implements Calculator{

    @Override
    public int add(int i, int j) {
        System.out.println("Log:method add begin:"+i+" and "+j);
        int result = i + j;
        System.out.println("Log:method add end:"+i+" and "+j);
        return result;
    }

    @Override
    public int sub(int i, int j) {
        System.out.println("Log:method div begin:"+i+" and "+j);
        int result = i - j;
        System.out.println("Log:method div end:"+i+" and "+j);
        return result;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 问题

上面代码实现了我们的日志需求,但是这种实现方式很是繁琐。而且日志模块和核心代码混杂在一起,使得后期维护也不是很方便。显然不是我们想要的。


使用动态代理解决以上问题

  • 核心代码块保持纯净,只负责自己的功能就行:
package com.spring.proxy;

public class CalculatorImpl implements Calculator{

    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 代理类
package com.spring.proxy;

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


public class CalculatorProxy{

    //引入被代理对象
    private Object target;

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



    public Object getCalcultorProxy() {

        Object proxy = null;
        //代理对象由哪个类加载器加载
        ClassLoader loader = target.getClass().getClassLoader();
        //代理对象的类型,即其中有哪些方法
        Class[] interfaces = target.getClass().getInterfaces();
        //处理方法
        InvocationHandler h = new InvocationHandler(){
             /**
             * proxy:正在返回的代理的对象,一般不去使用它
             * method: 被调用的方法
             * args: 被调用方法的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                String methodName = method.getName();
                //日志
                System.out.println("Log:method "+methodName+" begin:"+Arrays.asList(args));
                //执行方法
                Object result = method.invoke(target, args);
                //日志
                System.out.println("Log:method "+methodName+" end:"+Arrays.asList(args));

                return result;
            }
        };

        //创建代理对象
        proxy =  Proxy.newProxyInstance(loader, interfaces, h);

        return proxy;
    }


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 测试:
Calculator target = new CalculatorImpl();

Calculator proxy = (Calculator) new CalculatorProxy(target).getCalcultorProxy();
int result = proxy.add(1, 2);
System.out.println("-->"+result);
result = proxy.sub(2, 1);
System.out.println("-->"+result);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里写图片描述

  • 成功实现日志功能,而不影响Calcultor的核心实现代码
  • 但是这样还是相对麻烦,而且对程序员要求会很高。
  • 使用AOP可以很方便的解决上述问题。

认识AOP

  • AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充.
  • AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点在应用 AOP 编程时, 仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受影响的类. 
    这样一来横切关注点就被模块化到特殊的对象(切面)里.
  • AOP 的好处: 每个事物逻辑位于一个位置, 代码不分散, 便于维护和升级 业务模块更简洁, 只包含核心业务代码.

上面那个是比较官方的解释,有点难理解,下面用图解说明: 
这里写图片描述
简单认识下图中的一些专业术语:

  • 横切关注点:需要实现的一些附加功能,比如上面的日志功能等。
  • 切面(Aspect): 将横切关注点抽取出来定义成单独的模块。
  • 目标(Target): 需要添加附加功能的对象

本系列参考视频教程: http://edu.51cto.com/course/1956.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值