美文网首页我爱编程
SpringAOP以及动态代理

SpringAOP以及动态代理

作者: 西元前__YP | 来源:发表于2018-04-15 11:15 被阅读0次

AOP,即面向切面编程,算是OOP(面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构。OOP主要应对纵向的关系,而AOP则负责横向的关系,如事务管理,日志等。

AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。 这篇文章主要介绍Spring AOP。 关于AspectJ的内容可以之后再探索。

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。

如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

为动态代理和CGLIB做一个简单的比较:

  • 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
  • 如果目标对象实现了接口,仍然可以强制使用CGLIB实现AOP
  • 如果目标对象没有实现接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

在使用SpringAOP的过程中,或许有时会看到@AspectJ 这样的注解。不过Spring 只是使用了与 AspectJ 5 一样的注解,但没有使用 AspectJ 的编译器(ajc编译器),底层依然是动态代理技术的实现,因此并不依赖于 AspectJ 的编译器。

动态代理

介绍了许多关于代理的基本概念之后,进行动态代理的深入探究。JDK动态代理的核心是InvocationHandler接口和Proxy类。

Proxy类
我们主要通过这个类中的一个方法生成代理对象

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler invocationHandler throws IllegalArgumentException

其中第一个参数loader 代表类加载器(即哪个类加载器来加载这个代理类到 JVM 的方法区)
第二个参数是接口(表明这个代理类需要实现哪些接口),第三个参数是调用处理器类实例

这个函数是 JDK 为了程序员方便创建代理对象而封装的一个函数,因此你调用newProxyInstance()时直接创建了代理对象(略去了创建代理类的代码)。其实他主要完成了以下几个工作:

static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)
{
    //1. 根据类加载器和接口创建代理类
    Class clazz = Proxy.getProxyClass(loader, interfaces); 
    //2. 获得代理类的带参数的构造函数
    Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });
    //3. 创建代理对象,并制定调用处理器实例为参数传入
    Interface Proxy = (Interface)constructor.newInstance(new Object[] {handler});
}


Proxy 类中有一个映射表,映射关系为:(<ClassLoader>,(<Interfaces>,<ProxyClass>) ),可以看出一级key为类加载器,根据这个一级key获得二级映射表,二级key为接口数组,因此可以看出:一个类加载器对象和一个接口数组确定了一个代理类。

InvocationHandler接口

这个接口下只有一个方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable

在每次代理对象调用 实际接口 中的方法时,都会触发这个 invoke 方法,其中有三个参数

proxy参数 代表代理对象, method参数代表调用的具体的方法, args参数代表这个method所需要的具体参数

定义接口与实现类
接下来通过一个具体的例子查看如何实现动态代理

接口

public interface BuyTickets {

    String buy(String userName);

}

接口实现类

public class BuyTicketsImpl implements BuyTickets {

    public String buy(String userName) {

        String result = userName + "buy Success!";
        return result;
    }
}

生成代理

public class BuyTicketsProxy implements InvocationHandler {

    private Object subObject; //需要代理的目标对象

    public Object creatProxy(Object subObject){
        this.subObject = subObject;

        return Proxy.newProxyInstance(subObject.getClass().getClassLoader(), subObject.getClass().getInterfaces()
        ,this);
    }


    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("代理类名:" + proxy.getClass().getName());
        System.out.println("代理方法名:" + method.getName());
        Object result = null;

        System.out.println("----------begin method------------"); //这里可以织入其他切面逻辑
        result = method.invoke(this.subObject, args);
        System.out.println("between hhh" + result);
        System.out.println("----------end method ---------------");


        return result;
    }
}

测试

public class Main {

    public static void main(String []args){

        BuyTicketsProxy buyTicketsProxy = new BuyTicketsProxy();

        //利用Proxy 创建一个代理实例
        BuyTickets buyTickets = (BuyTickets) buyTicketsProxy.creatProxy(new BuyTicketsImpl());

        String result = buyTickets.buy("LYP");

        System.out.println(result);

    }
}

结果

代理类名:com.sun.proxy.$Proxy0
代理方法名:buy
----------begin method------------
between hhhLYPbuy Success!
----------end method ---------------
LYPbuy Success!

参考:
https://isudox.com/2017/05/24/spring-aop-guide/

相关文章

  • 面试系列~动态代理实现与原理

    动态代理有JDK动态代理, CGLIB动态代理, SpringAOP动态代理 一,JDK动态代理  jdk动态代理...

  • Spring AOP 一

    上一篇讲了jdk动态代理,下面我们来说说SpringAOP。SpringAOP是基于动态代理的,它对动态代理又做了...

  • SpringAOP以及动态代理

    AOP,即面向切面编程,算是OOP(面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次...

  • Spring_AOP_02——实现原理

    本文主要讲实现AOP的 代理模式原理,以及静态代理,动态代理的区别和具体实现。 对SpringAOP的概念和使用,...

  • Spring学习(五)AOP

    SpringAop使用到了了动态代理模式(有关设计模式见设计模式章节)。JDK动态代理代理的目标类必须要实现接口。...

  • JVM_字节码:字节码层面看看动态代理

    SpringAop是基于动态代理的,主要有2种方式:JDK的动态代理,CGLIB的代理,增加织入的功能。 JDK动...

  • SpringAOP-jdk动态代理

    静态代理与动态代理 静态代理(如SpringAOP-代理模式中所示)的缺点代理目标的方法越多,代理所委托的方法就越...

  • SpringAOP

    springAOP实现方式 1.动态代理 使用 Proxy机制,使用反射技术,创建实际对象的代理对象,添加AOP的...

  • 代理模式

    代理模式的典型就是springAOP代理模式的目的有两个:保护目标对象,增强目标对象分类:静态代理和动态代理。 静...

  • 动态代理,SpringAOP,AspectJ

    跟我学AspectjSpring AOP,AspectJ, CGLIB 有点晕aspectj Proxy 那点事儿...

网友评论

    本文标题:SpringAOP以及动态代理

    本文链接:https://www.haomeiwen.com/subject/qvrdkftx.html