AOP简介

AOP

产生的原因

  1. 多个方法执行相同的代码

  2. 将相同的代码抽取出来,形成公用的方法,在需要的地方进行显示调用,这样能满足一个功能在多个方法(M1,M2,M3)中被调用。

  3. 如果新增几个功能,也是在同样的方法(M1,M2,M3)中调用,那这样的话就要修改那些需要调用的方法。这样又要修改(M1,M2,M3)这些方法,增加一定的工作量!最好是不要修改这些方法,不要在这些方法中显示地调用功能。这样AOP的思想随之诞生。

AOP的定义

AOP(Aspect Orient Programming),面向切面编程的思想。它使用生成代理对象的方式,来控制对target兑现的访问。生成代理对象的方式有JDK动态代理和cglib。

  1. 怎么选择生成代理对象的方式
    目标对象如果实现了接口,就使用JDK动态代理 。
    目标对象如果继承了类,则使用cglib。

AOP通知的类型

public int sayHello(){
    try{
    } catch(Exception e){
    } finally{
    }
    return 1;   
} 
  • 前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
  • 后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
  • 异常通知(After throwing advice):在方法抛出异常退出时执行的通知。
  • 最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。

利用JDK动态代理来实现

  • interface
public interface Calculator {

    int calculate(int a, int b);

    int multiplute(int a , int b);

    int divide(int a, int b);
}
  • implClass

public class CalculatorImpl implements Calculator {

    @Override
    public int calculate(int a, int b) {
        System.out.println("Im doing");
        return a+b;
    }

    @Override
    public int multiplute(int a, int b) {
        return a*b;
    }

    @Override
    public int divide(int a, int b) {
        return a/b;
    }
}
  • ProxyFactory
public class ProxyFactory {
    public static Object getProxy(Object targetObject, List<AbstractHandler> handlers) {
        Object proxyObject = null;
        if (handlers.size() > 0) {
            proxyObject = targetObject;
            for (int i = 0; i < handlers.size(); i++) {
                handlers.get(i).setTargetObject(proxyObject);
                proxyObject = Proxy.newProxyInstance(targetObject.getClass()
                        .getClassLoader(), targetObject.getClass()
                        .getInterfaces(), handlers.get(i));
            }
            return proxyObject;
        } else {
            return targetObject;
        }
    }
}
  • 前置通知

public abstract class AbstractHandler implements InvocationHandler{

    private Object targetObject ;

    public void setTargetObject(Object targetObject) {
        this.targetObject = targetObject;
    }

    public Object getTargetObject() {
        return targetObject;
    }
}

public  abstract  class BeforeHandler extends  AbstractHandler{

    public abstract void handleBefore(Object proxy, Method method, Object[] args);

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        handleBefore(proxy, method, args);
        return method.invoke(getTargetObject(), args);
    }
}

  • test

public class Client {

    public static void main(String[] args) throws IOException {

        Calculator calculator = new CalculatorImpl();

        BeforeHandler beforeHandler = new BeforeHandler(){
            @Override
            public void handleBefore(Object proxy, Method method, Object[] args) {
                System.out.println("handleBefore");
            }
        };

        List<AbstractHandler> handlerList = new ArrayList<>();
        handlerList.add(beforeHandler);
        Calculator proxy = (Calculator) ProxyFactory.getProxy(calculator, handlerList);

        System.out.println(proxy.divide(1,1));
    }
}

Spring AOP

  • 同一个连接点有多个切面的同一通知,怎么确定顺序

使用 org.springframework.core.annotation.Order; 来确定顺序
value值越小,放在前面执行

  1. https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/
  2. http://shouce.jb51.net/spring/aop.html
  3. https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值