java动态代理

jdk动态代理

helloWorld

好了,在介绍完这两个接口(类)以后,我们来通过一个实例来看看我们的动态代理模式是什么样的:

思路:

我们helloworld中有两个接口,一个接口是自定义的,另一个是创建动态代理类所需要实现的InvocationHandler接口。

有两个对象:真实对象(实现自定义接口)、代理对象(实现InvocationHandler接口)、代理对象

首先我们定义了一个Subject类型的接口,为其声明了两个方法:

接口
//自定义接口
public interface UserService {
    String hello();//测试无参
    public String getUserByName(String name); //测试有参
}
真实对象

接着,定义了一个类来实现这个接口,这个类就是我们的真实对象,RealSubject类:

//真实对象(被代理对象)
public class UserServiceImpl implements UserService {
    @Override
    public String hello() {
        return "hello";
    }

    @Override
    public String getUserByName(String name) {
        System.out.println("从数据库中查询到:" + name);
        return name;
    }
}

下一步,我们就要定义一个动态代理类了,前面说个,每一个动态代理类都必须要实现 InvocationHandler这个接口,因此我们这个动态代理类也不例外:

InvocationHandler

写明我们的代理逻辑:实现InvocationHandler接口,在invoke方法中编写代理逻辑,这个实现类作为handler

我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

interface InvocationHandler{
    Object invoke(Object proxy, // 代理对象
                  Method method, 
                  Object[] args) throws Throwable;
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyHandler implements InvocationHandler {

    // 目标类对象
    private Object target;

    // 构造器传入目标类对象
    public MyHandler(Object target) {
        this.target = target;
    }

    // 创建JDK代理 // 为什么要放在handler里创建代理对象:spring也是这么做的,工厂同时也是handler
    public Object createJDKProxy() {
        Class clazz = target.getClass();
        // 创建JDK代理需要3个参数,目标类加载器、目标类接口、代理类对象(即本身)
        return Proxy.newProxyInstance(
            clazz.getClassLoader(), // 传入加载器
            clazz.getInterfaces(),  // 传入接口
            this); // 传入handler对象 // 代理的逻辑
        // 创建了代理对象
    }

    @Override
    public Object invoke(Object proxy,
                         Method method,
                         Object[] args) throws Throwable {
        //  在代理真实对象前我们可以添加一些自己的操作
        System.out.println("前置通知");
        Object result = method.invoke(target, args);//通过反射调用传入真实对象subject的方法method,method方法的参数是args
        //  在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("后置通知");
        return result;
    }
}

handler一般都要实现如下内容

  • 构造函数:将目标对象传入
  • 重写invoke():写AOP增强的所有逻辑
  • 重写getProxy():这个方法并不是我们InvocationHandler接口的方法,但是写在handler实现类中后handler就能产生代理对象了,也就是说handler同时是代理工厂+handler

当然我们上面的处理逻辑要用到的时候利用lambda表达式直接new也行

创建代理实例
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;

public class Test {

    public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
//        System.getProperties().put("com.proxy.ProxyGenerator.saveGeneratedFiles","true");
        UserService userService = new UserServiceImpl();
        MyHandler myHandler = new MyHandler(userService);// 会调用接口的实现类对象
        // 获取代理对象
        UserService proxy = (UserService) myHandler.createJDKProxy();

        // 输出看看代理对象的类型
        System.out.println(proxy.getClass());// com.sun.proxy.$Proxy0

    }
}
生成的代理类

JDK动态代理的原理还是反射,如

package com.sun.proxy;

import JDK.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

// 继承了Proxy,里面的方法是调用的super.h.invoke()。
public final class $Proxy0 extends Proxy implements UserService {
    // 父类为Proxy、UserService
    
    private static Method m1;
    private static Method m3;
    private static Method m4;
    private static Method m2;
    private static Method m0;

    // 将handler对象传给父类Proxy,父类中有成员属性InvocationHandler
    public $Proxy0(InvocationHandler var1) throws  { // 构造器传入InvocationHandler
        super(var1);//调用父方法的有参构造 // 赋给父类的属性h即 this.h = h;获取时是super.h
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    
    public final String hello() throws  {
        try {
            // 即调用handler对象的invoke方法, 这里的内容其实基本是我们写过的
            return (String)super.h.invoke(this,  //代理对象,我们终于知道MyHandler.invoke()的第一个参数是什么了
                                          m3, // m3为hello()的method对象
                                          (Object[])null);// // hello()的method的参数
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    
    public final String getUserByName(String var1) throws  {
        try {
            return (String)super.h.invoke(this, // 代理对象
                                          m4,// m4 为getUserByName()的method对象
                                          new Object[]{var1}); // 1个参数
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            // 拿到method对象
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            // 无参hello()
            m3 = Class.forName("JDK.UserService").getMethod("hello");
            // 有参getUserByName(String)
            m4 = Class.forName("JDK.UserService").getMethod("getUserByName", Class.forName("java.lang.String"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

helloworld进阶:https://blog.csdn.net/qq_27717967/article/details/73561179

将内存中的动态代理对象生成class文件

代理class的生成路径是在idea的工作空间下的 com\sun\proxy 目录中,如下图所示

//保存生成的对象
public static void generateClassFile(Class clazz, String ProxyName){//$Proxy0
    
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
        proxyName, 
        clazz.class.getInterfaces() );//生成了字节数组(字节码)

    //String path = clazz.getResource("").getPath();
    String path="C:/";
    paths.sout;
    FileOutputStream out=null;
    try{
        out = new FileOutputStream(path+ProxyName+".class");
        out.write(proxyClassFile);
        out.flush();
    }finally{
            out.close();
    }
}

cglib生成class文件:

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "e:\\class");

jdk动态代理源码解读

Proxy.newProxyInstance()

  • getProxyClass0(loader类加载器, intfs接口列表)获得代理类
  • cl.getConstructor(constructorParams构造器形参列表);反射得到代理类构造器
  • cons.newInstance(new Object[]{h}); 反射创建代理实例对象
@CallerSensitive // Proxy
public static Object Proxy.newProxyInstance(
    ClassLoader loader, //一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
    Class<?>[] interfaces, //一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
    InvocationHandler h)//一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上 // 重写了invoke方法
    throws IllegalArgumentException {
    //检验handler不为空,为空的话没有代理逻辑,所以得报错
    Objects.requireNonNull(h);

    // 拷贝一份接口类
    final Class<?>[] intfs = interfaces.clone();
    //获得安全管理器,进行一些安全性检查
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }

    //-----------重要----------------------
    // 从缓存中拿到代理class对象,当然可能拿不到,就创建//生成代理类字节码以及加载都在这里进行
    // 一组接口只能生成一个代理类,因为从缓存中拿是以类加载器和接口来取的,如果想要同组接口不同的代理类,得变类加载器
    Class<?> cl = getProxyClass0(loader, intfs);//生成字节码,生成class对象//接口复数
    //从上步出来已经有代理类了,接下来没有那么重要,还是上句最重要,所以我们得点进去看
    //------------------------------
    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }

        // --------重要-------------
        //从生成的代理类中获取构造函数,具体哪个构造函数可以通过constructorParams指定,是个Class数组
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        //如果代理类是不可访问的, 就使用特权将它的构造器设置为可访问
        if (!Modifier.isPublic(cl.getModifiers())) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    cons.setAccessible(true);
                    return null;
                }
            });
        }
        // 生成代理对象,传入构造参数,将InvocationHandler作为参数,实例化代理对象
        return cons.newInstance(new Object[]{h});// 参数为InvocationHandler对象
    } catch (IllegalAccessException|InstantiationException e) {
        throw new InternalError(e.toString(), e);
    } catch (InvocationTargetException e) {
        Throwable t = e.getCause();
        if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            throw new InternalError(t.toString(), t);
        }
    } catch (NoSuchMethodException e) {
        throw new InternalError(e.toString(), e);
    }
}

二、Proxy.getProxyClass0()

1、Proxy.getProxyClass0()

获取符合loader+intfs的代理类Class对象,参数为类加载器和接口类。

没有就创建

  • proxyClassCache代理类缓存.get(loader类加载器, interfaces接口列表);
// Proxy.java
private static Class<?> getProxyClass0(ClassLoader loader,
                                       Class<?>... interfaces) {
    //接口的数量是否大于65535,报错
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");11
    }

    // 如果缓存类中已经存在实现了对应接口的代理类,那么直接返回缓存副本即可,
    // 否则将通过代理工厂ProxyClassFactory创建代理类
    return proxyClassCache.get(loader, interfaces);
    // 说一下在这里invocationHandler去哪了:生成代理类的时候逻辑是按照接口来的,跟h没有关系,直到生成具体的代理实例时才传入h生成具体的代理对象
    // 生成的代理类的构造函数的参数就是ih
}

2、proxyClassCache

上面最重要的是代理类缓存WeakCache,他是什么呢?

proxyClassCacheProxy.java中的一个静态属性,在JVM加载类的时候就加载好了

  • proxyClassCache用于通过类加载和接口获得生成的代理类class
  • <ClassLoader, Class<?>[], Class<?>>的意思是通过类加载器+接口数组,得到一个代理类
// proxyClassCache静态属性 //Proxy.java
// 新建了一个WeakCache类型的对象,该类型构造方式为传入key工厂和代理类工厂
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache 
    = new WeakCache<>(new KeyFactory(), //作为subKeyFactory,产生二级map的副key
                      new ProxyClassFactory()); //作为valueFactory,生成代理类
2.1 WeakCache类基础介绍

proxyClassCache的类型是WeakCache

2.0) WeakCache的构造函数:
  • BiFunction介绍:https://www.jianshu.com/p/8dc46a2dc21d

  • WeakCache要起到的一个效果是用主副键得到一个值:{(key,sub-key)-->value}

  • WeakCache<K,P,V>中,K代表key值,P代表参数,V代表存储的值。
        此类用于缓存{(key,sub-key)-->value}键值对。
        具体实现是一个ConcurrentMap<Object,ConcurrentMap<Object,Supplier<V>>>
        (Supplier是一个接口,就一个get方法用于获得值,不过是V的包裹类),
        第一个Object就是key(这里表达式不用K是因为key值可以为null),
        第二个Object就是sub-key。
    

根据 ,我们知道WeakCache的构造函数传入了两个BiFunction函数。BiFunction函数是代表传入两个参数,返回一个返回值的函数,类似于我们原来的函数式接口

而在WeakCache实例化的时候,传入了两个BiFunction函数(他同时也是一个类),分别是subKeyFactoryvalueFactory,首先明确他们是两个函数。其次这两个参数实参分别是subKeyFactory=new KeyFactory()
valueFactory=new ProxyClassFactory()
那么就知道了KeyFactory和ProxyClassFactory肯定实现了BiFunction这个类

而事实上在Proxy的内部类中KeyFactory确实证实了我们的猜想。但我们往下看的话会很晕,我们得先记住:

  • Object KeyFactory.apply(classLoader,Class<?>[] interfaces)体会一下它的参数和返回值
  • Class<?> ProxyClassFactory.apply(ClassLoader,Class<?>[] interfaces) 拿到最终的代理类
//K代表key的类型,P代表参数的类型,V代表value的类型。
// WeakCache<ClassLoader, Class<?>[], Class<?>>  proxyClassCache  说明proxyClassCache存的值是Class<?>对象,正是我们需要的代理类对象。
final class WeakCache<K, P, V> {

    private final ReferenceQueue<K> refQueue
        = new ReferenceQueue<>();
    
    // 两个map
    // the key type is Object for supporting null key
    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
        = new ConcurrentHashMap<>();
    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
        = new ConcurrentHashMap<>();
    
    // 两个工厂 // K为类加载器,P为接口数组,V为代理类Class<?>
    private final BiFunction<K, P, ?> subKeyFactory; // 生成subKey
    private final BiFunction<K, P, V> valueFactory; //ProxyClassFactory // 生成代理类


    // 构造函数
    public WeakCache(BiFunction<K, P, ?> subKeyFactory,
                     BiFunction<K, P, V> valueFactory) {
        this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
        this.valueFactory = Objects.requireNonNull(valueFactory);
    }

WeakCache主要内容

  • V get(K key, P parameter)
  • boolean containsValue(V value)
  • int size()
  • expungeStaleEntries()
  • ReferenceQueue<K> refQueue
  • ConcurrentHashMap<Object, ConcurrentMap<Object, Supplier<V>>> map:最重要。相当于依赖2个key才能得到一个值,表示为(key, sub-key) -> value
    • key是传进来的Classloader进行包装后的对象,
    • sub-key是由WeakCache构造函数传入的KeyFactory()生成的。
    • value就是产生代理类的对象,是由WeakCache构造函数传入的ProxyClassFactory()生成的。

我们再从语言上理解下刚才的这两句:
subKeyFactory=new KeyFactory() 生产key
valueFactory=new ProxyClassFactory() 生产代理类对象

好吧,他们的参数是都是加载器+接口,返回值分别是ObjectClass

我们知道了现在WeakCache对象中有了一些功能,你只要传入一个加载器+接口,我们就可以得到一个

再根据前面的(cachekey, sub-key) -> 工厂

ConcurrentMap<Object cachekey, 
			  ConcurrentMap<Object sub-key, 
				  		   Supplier<V> supply> 
             >  map
两个BiFunction.apply()
1) 一级工厂KeyFactory.apply生成接口弱引用

它又被称为subKeyFactory

  • 继承BiFunction,代表输入两个参数,输出一个参数
  • KeyFactory的功能就是传入接口,生成接口的若引用(被称为KeyX)
private static final class KeyFactory
    implements BiFunction<ClassLoader, Class<?>[], Object>
{
    @Override // 返回Object类型 // 即输入两个参数,输出一个参数 //得到的object对象就是个id而已
    public Object apply(ClassLoader classLoader, // 参数1
                        Class<?>[] interfaces) { // 参数2
        // 判断接口数量
        switch (interfaces.length) {
            case 1: return new Key1(interfaces[0]); // 1个接口 // 里面是先算hash值然后创建接口的弱引用
            case 2: return new Key2(interfaces[0], interfaces[1]); // 2个接口 // 为每个接口生成弱引用
            case 0: return key0; // 没有接口
            default: return new KeyX(interfaces); // 多个接口 // 为每个接口生成弱引用
        }
    }
}
我们可以观察到,根本没用到classLoader
    KeyFactory的功能就是传入接口,生成接口的若引用(被称为KeyX);


private static final class KeyX {
    private final int hash;
    private final WeakReference<Class<?>>[] refs;
    
    // KeyX构造函数,生成接口弱引用后放到数组refs[]中。Key1和Key2也差不多
    KeyX(Class<?>[] interfaces) {
        hash = Arrays.hashCode(interfaces);
        refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length];
        for (int i = 0; i < interfaces.length; i++) {
            refs[i] = new WeakReference<>(interfaces[i]);
        }
    }

上面就是对接口生成了弱引用。

弱引用:该引用一旦经历垃圾回收,该不再引用

2) 二级工厂ProxyClassFactory.apply生成代理类

它又被称为valueFactory

  • 代理类名称样式案例:$Proxy3.class
  • 前缀:代理类的前缀是"$Proxy"
  • 序号:代理类的序号是通过AtomicLong保证的
  • 所在包:默认生成的包名是com.sun.proxy,如果接口有不是public,生成在该接口所在包下,如果非public的接口原来不都在同一个包下,那么将报错
  • 访问权限:默认的代理类访问权限是public final,如果有接口不是public,那么访问权限变为final,去掉public
  • 同样是继承了BiFunction,输入两个参数,输出一个参数
  • 两个参数分别是ClassLoader loader和 Class<?>[] interfaces,返回值是生成的代理类Class<?>
//代理类生成工厂 // 前面的缓存中第二个参数
private static final class ProxyClassFactory
    implements BiFunction<ClassLoader, Class<?>[], Class<?>> {//这里的BiFunction输入是(类加载器+接口数组),返回代理类
    //代理类名称前缀
    private static final String proxyClassNamePrefix = "$Proxy";
    // 生成代理类的序号, 以此来确定唯一的代理类 // 原子long
    private static final AtomicLong nextUniqueNumber = new AtomicLong();

    @Override // apply意思是既是消费者也是生产者
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
        // IdentityHashMap如果提交重复的key,那么都会存储,但是他们get方法会返回null 
        Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);//map大小
        for (Class<?> intf : interfaces) {
            Class<?> interfaceClass = null;
            interfaceClass = Class.forName(intf.getName(), false, loader);
            //这里遍历interfaces数组进行验证, 主要做三件事情
            //1.intf是否可以由指定的类加载进行加载
            //2.intf是否是一个接口
            //3.intf在数组中是否有重复
            
            // 然后我们发现这个for里只是检验
        }
        //生成代理类的包名
        String proxyPkg = null;
        //生成代理类的访问标志, 默认是public 且 final的
        int accessFlags = Modifier.PUBLIC | Modifier.FINAL; // 00....011
        for (Class<?> intf : interfaces) {
            //获取接口的访问标志
            int flags = intf.getModifiers();
            //如果接口的访问标志不是public, 那么生成代理类的包名和接口包名相同
            if (!Modifier.isPublic(flags)) {
                //生成的代理类的访问标志设置为final,注意不是public了
                accessFlags = Modifier.FINAL;
                //获取接口全限定名, 例如:java.util.Collection
                String name = intf.getName();
                int n = name.lastIndexOf('.');
                //剪裁后得到包名:java.util
                String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                //生成的代理类的包名和接口包名是一样的
                if (proxyPkg == null) {// 第一个接口进来时候是null,第二个接口进来就!=null
                    proxyPkg = pkg;
                } else if (!pkg.equals(proxyPkg)) {
                    //代理类如果实现不同包的接口, 并且接口都不是public的, 那么就会在这里报错
                    throw new IllegalArgumentException(
                        "non-public interfaces from different packages");
                }
            }
        }
        // 如果接口都是public的话, 那生成的代理类都放到默认的包下:com.sun.proxy
        if (proxyPkg == null) {
            proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }
        //生成代理类的序号,该类是原子类
        long num = nextUniqueNumber.getAndIncrement();
        //生成代理类的全限定名, 包名+前缀+序号, 例如:com.sun.proxy.$Proxy0
        String proxyName = proxyPkg + proxyClassNamePrefix + num;
        // ---------核心代码-----------
        // 用sun.misc.ProxyGenerator来生成字节码
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, // 生成的类名字
                                                                  interfaces,  // 接口
                                                                  accessFlags); // 代理类类型final或者public final的
        try {
            //根据二进制文件生成相应的Class实例 //native
            return defineClass0(loader, proxyName,
                                proxyClassFile,// 二进制
                                0, proxyClassFile.length);
        } catch (ClassFormatError e) {
            throw new IllegalArgumentException(e.toString());
        }
    }
}
3、 proxyClassCache.get()

先说明一下这步是从哪来的,我们前面是介绍了proxyClassCache的组成是个WeakCache,显示它不是动态代理的逻辑了,那么何如通过它得到我们的代理类呢?

答案在于通过构造函数中传入的两个BiFunction来一步步回调得到最终的代理类。换句话说,WeakCache只知道怎么调用两个连接两个BitFunction最终得到一个值,而动态代理只需要提供两个BitFunction即可。而这两个BitFunction我们之前讲过了

跟踪proxyClassCache.get(loader, interfaces);本段代码我们主要关心V value = supplier.get();其中supplier本质是factory,通过new Factory(key, parameter, subKey, valuesMap)创建

  • cacheKey= CacheKey.valueOf(key, refQueue); 得到主键,主键从一级map里拿二级map
  • valuesMap=map.get(cacheKey) 一级map里拿到二级map,也就是用类加载器拿到二级map
  • subKey= subKeyFactory.apply(key类加载器, parameter接口类); 一级工厂,产生二级key,二级key是接口的封装
    • 副键,依靠它从二级map里得到能生成最终值的生产者
  • supplier = valuesMap.get(subKey); 二级map
  • V value = supplier.get();生产者生产值
// 伪代码
public V  proxyClassCache.get(K key, //类加载器
                              P parameter) {// 接口
    // cacheKey=key+refQueue
    // 主缓存key=类加载器+弱引用队列
    Object cacheKey = CacheKey.valueOf(key, refQueue);
    // 用缓存key(主key) 从map 拿到二级valuesMap  。
    // 这里主要利用的是类加载器
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);

    // subKey=key+parameter
    // 用subKeyFactory的BiFunction传入key+parameter返回Object   即返回subKey(副key),但其实这个key只有接口的信息
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    // 从二级map中取得subkey对应的supplier,supplier即工厂
    // 这里主要利用的是接口的弱引用
    Supplier<V> supplier = valuesMap.get(subKey);
    // 从工厂中拿到代理对象拿到代理对象
    V value = supplier.get();
    return value;
}
// WeakCache.get()
public V proxyClassCache.get(K key, //类加载器
                             P parameter) {//接口类

    // Object工具类  类加载器为空抛出异常用于验证
    Objects.requireNonNull(parameter);

    // 将被clear的key值对应值从map中删除
    expungeStaleEntries();

    //map中的key值和value值都是弱引用,这里valueOf静态方法,返回key的新建弱引用对象,
    //这里有一点要注意CacheKey弱引用对象的hash值跟key值绑定,所以虽然新建了弱引用对象
    //但是key值一样在map中就能取到对应的值
    // 用 类加载器+引用队列(就是接口列表) 组成 缓存key,如果key==null,则cacheKey=new Object();
    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // 用缓存key从一级map中拿到二级map // 懒汉模式
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);

    // 下面的整个if其实就是单例模式创建一个map给cachekey对应的二级map而已
    // 如果二级map值map为空,就新增

    if (valuesMap == null) {
        // putIfAbsent:不存在才添加后返回null,如果有就直接返回现有值,不修改
        // 按理说我们创建的时候为了同步需要加锁,但是ConcurrentMap本来就是线程安全的了,假设线程1,2同时到达此处,线程1先进去后设置完了返回null,线程2进入后返回线程1传入的值
        // 同时注意参数2在传入的同时还赋值给valuesMap了
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        // 线程1拿到的是null,跳过下面if //线程2拿到的是线程1的值,按理来说拿到线程1的值不是正好吗,接着往下执行不就行了,但是注意上面线程2new的时候改变valuesMap的值了,所以得改变回去
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }
    /* 常见的懒汉模式
   if(map==null){
		synchronized (map.class){
			if(map==null){
				map=new Map();
			}
		}
	}
	return map; 
    */

    // 传入key和parameter到subKeyFactory函数中得到subKey
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));//apply生成
    // 通过sub-key从valuesMap得到supplier,实质就是factory
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;


    // // Proxy.newStance第一次执行的时候,supplier,valuesMap都为null。下面从序号①-⑤看
    while (true) {
        // 从工厂中获得类对象
        if (supplier != null) {
            // ④从工厂中获得代理类对象
            // supplier可以是一个工厂或是一个缓存实例
            V value = supplier.get();
            if (value != null) {
                // ⑤返回代理类对象
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // ①懒加载工厂
        if (factory == null) {
            // 创建对应factory,此段代码在死循环中,下一次supplier.get()将会获取到代理类并退出循环
            factory = new Factory(key, 
                                  parameter, 
                                  subKey, 
                                  valuesMap);
        }

        // 懒汉模式给valuesMap中subKey对应的值supplier
        if (supplier == null) {
            // ②把工厂保存到valuesMap中
            // 有则返回旧值不替换,无则传入新值返回null
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // ③赋值
                // factory已经放到valuesMap中了
                supplier = factory;
            }
            // else retry with winning supplier
        } else {// 如果原来不为空但是获得不到value,重新弄个新的
            // replace的作用的只有在前两个参数组成的键值对匹配的时候才替换
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}

从proxyClassCache.get()就能得到代理对象了,那么代理对象一定是在proxyClassCache.get()的某一步生成的。从上面可知是从工厂里获得的,那么就有必要了解一下工厂,即supplier

supplier.get()
// 内部类Factory.java    
public synchronized V get() { // serialize access
    // re-check
    // 再次检查,supplier是否是当前对象
    Supplier<V> supplier = valuesMap.get(subKey);
    if (supplier != this) {
        // something changed while we were waiting:
        // might be that we were replaced by a CacheValue
        // or were removed because of failure ->
        // return null to signal WeakCache.get() to retry
        // the loop
        return null;
    }
    // else still us (supplier == this)

    // create new value
    V value = null;
    try {
        // 关键
        // valueFactory就是WeakCache的valueFactory属性,因为Factory是WeakCache的内部类,所以可以直接访问WeakCache的valueFactory属性,即new ProxyClassFactory(),他是一个BiFunction
        // 即传入subkey返回代理对象 //通过类加载器+接口得到一个代理类
        value = Objects.requireNonNull(valueFactory.apply(key, parameter));
    } finally {
        if (value == null) { // remove us on failure
            valuesMap.remove(subKey, this);
        }
    }
    // the only path to reach here is with non-null value
    assert value != null;

    // wrap value with CacheValue (WeakReference)
    CacheValue<V> cacheValue = new CacheValue<>(value);

    // put into reverseMap
    reverseMap.put(cacheValue, Boolean.TRUE);

    // try replacing us with CacheValue (this should always succeed)
    if (!valuesMap.replace(subKey, this, cacheValue)) {
        throw new AssertionError("Should not reach here");
    }

    // successfully replaced us with new CacheValue -> return the value
    // wrapped by it
    return value;
}

调用了valueFactory.apply(key, parameter)

ProxyGenerator.generateProxyClass

创建动态代理class文件

public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
    ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
    final byte[] var4 = var3.generateClassFile();
    if (saveGeneratedFiles) {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                try {
                    int var1 = var0.lastIndexOf(46);
                    Path var2;
                    if (var1 > 0) {
                        Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                        Files.createDirectories(var3);
                        var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                    } else {
                        var2 = Paths.get(var0 + ".class");
                    }

                    Files.write(var2, var4, new OpenOption[0]);
                    return null;
                } catch (IOException var4x) {
                    throw new InternalError("I/O exception saving generated file: " + var4x);
                }
            }
        });
    }

    return var4;
}

cglib动态代理

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,cglib的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

CGLIB是一个强大的高性能的代码生成包。被广泛的许多AOP框架使用,如Spring的AOP和dynaop,为他们提供方法的interceptor(拦截),最流行的是OR Mapping工具Hibernate也是使用CGLIB来代理单端的single-ended(多对一和一对一)关联(对集合的延迟抓取是采用其他机制实现)。

  1. 静态代理和 JDK 代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是 Cglib 代理

  2. Cglib 代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将Cglib 代理归属到动态代理。

  3. Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口.它广泛的被许多 AOP 的框架使用,例如 Spring AOP,实现方法拦截

  4. 在 AOP 编程中如何选择代理模式:

\1. 目标对象需要实现接口,用 JDK 代理

\2. 目标对象不需要实现接口,用 Cglib 代理

  1. Cglib 包的底层是通过使用字节码处理框架 ASM 来转换字节码并生成新的类

在内存中动态构建子类,注意代理的类不能为 final,否则报错

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class EnhancerDemo {
    public static void main(String[] args) {

        // 1 new Enhancer增强器
        Enhancer enhancer = new Enhancer();
        // 2 给增强器中传入父类(目标对象类)
        enhancer.setSuperclass(EnhancerDemo.class);
        // 3 回调方法  // 把实现了MethodInterceptor接口的对象传入增强器,作为回调
        enhancer.setCallback(new MethodInterceptImpl()); // this里的intercept方法有代理逻辑
        // 4 创建代理对象   可以返回后强制转型
        EnhancerDemo demo = (EnhancerDemo) enhancer.create();

        demo.test();
        System.out.println("-----分割线----下面是System.out.println(demo);的内容---");
        System.out.println(demo);
    }

    public void test() {
        System.out.println("目标方法test()被执行");
    }

    // 内部类,定义在外面也可以
    private static class MethodInterceptImpl implements MethodInterceptor {

        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy)
            throws Throwable {
            System.out.println("before方法被执行:" + method);
            Object result = methodProxy.invokeSuper(obj, args);
            System.out.println("after方法被执行:" + method);
            return result;
        }
    }
}

输出

before方法被执行:public void com.example.demo.EnhancerDemo.test()
目标方法test()被执行
after方法被执行:public void com.example.demo.EnhancerDemo.test()
//-----分割线----下面是System.out.println(demo);的内容---
before方法被执行:public java.lang.String java.lang.Object.toString()
before方法被执行:public native int java.lang.Object.hashCode()
after方法被执行:public native int java.lang.Object.hashCode()
after方法被执行:public java.lang.String java.lang.Object.toString()
com.example.demo.EnhancerDemo$$EnhancerByCGLIB$$c9489e6f@41975e01

思路2

public class ProxyFactory implements MethodInterceptor {

	//维护一个目标对象
	private Object target;
	
	//构造器,传入一个被代理的对象
	public ProxyFactory(Object target) {
		this.target = target;
	}

	//返回一个代理对象:  是 target 对象的代理对象
	public Object getProxyInstance() {
		//1. 创建一个工具类
		Enhancer enhancer = new Enhancer();
		//2. 设置父类
		enhancer.setSuperclass(target.getClass());
		//3. 设置回调函数 MethodInterceptor
		enhancer.setCallback(this);
		//4. 创建子类对象,即代理对象
		return enhancer.create();
		
	}
	

	//重写  intercept 方法,会调用目标对象的方法
	@Override
	public Object intercept(Object arg0, // 被代理对象
                            Method method,  // 被代理对象的方法
                            Object[] args,  // 
                            MethodProxy arg3) throws Throwable {
		System.out.println("Cglib代理模式 ~~ 开始");
		Object returnVal = method.invoke(target, args);
		System.out.println("Cglib代理模式 ~~ 提交");
		return returnVal;
	}
}

首先调用了toString(),然后调用hashCode(),

同时可以看到这个类已经改变了,实际上CGLIB代理的类是委托给Cglib2AopProxy类去实现的。

按照前面的示例,我们容易判断出来,Cglib2AopProxy的入口应该是getProxy,也就是说在Cglib2AopProxy类的getProxy()中实现了Enhancer的创建及接口封装。

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
    }

    try {
        Class<?> rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

        Class<?> proxySuperClass = rootClass;
        if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
            proxySuperClass = rootClass.getSuperclass();
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();
            for (Class<?> additionalInterface : additionalInterfaces) {
                this.advised.addInterface(additionalInterface);
            }
        }

        // 验证class
        // Validate the class, writing log messages as necessary.
        validateClassIfNecessary(proxySuperClass, classLoader);

        // 创建及配置CGLIB Enhancer...
        Enhancer enhancer = createEnhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
            if (classLoader instanceof SmartClassLoader &&
                ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        // 设置目标列
        enhancer.setSuperclass(proxySuperClass);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

        // 设置拦截器
        Callback[] callbacks = getCallbacks(rootClass);
        Class<?>[] types = new Class<?>[callbacks.length];
        for (int x = 0; x < types.length; x++) {
            types[x] = callbacks[x].getClass();
        }
        // fixedInterceptorMap only populated at this point, after getCallbacks call above
        enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);

        // 生成代理类、创建代理对象
        return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (CodeGenerationException | IllegalArgumentException ex) {
        throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
                                     ": Common causes of this problem include using a final class or a non-visible class",
                                     ex);
    }
    catch (Throwable ex) {
        // TargetSource.getTarget() failed
        throw new AopConfigException("Unexpected AOP exception", ex);
    }
}

工厂

工厂是做什么的?

工厂可以根据传入的handler目标对象的类的信息自动判断是生成cglib的动态代理还是jdk动态代理。

ProxyFactory-helloWorld

前言

本篇将重点剖析ProxyFactory类的源码,很多人不理解为什么要将大部分精力花在讲解ProxyFactory上,毕竟没有人会使用这么底层的Spring AOP实现方式?

ProxyFactory实现代理需要手动设置Traget(目标对象)、Interface(代理接口)、Advice(增强),然后调用getProxy生成代理对象。而使用注解形式的Spring AOP并没有想象中的复杂,不过是寻找所有@Aspect注解的类以及所有@Before等增强,再通过@Pointcut上的匹配条件进行匹配,最后获取到所有匹配的Advice(增强)进行生成代理。因此,注解形式的AOP并不深奥,只不过是帮我们自动寻找匹配增强,并在Spring Ioc创建Bean的过程中寻找合适的时机,调用getProxy生成代理,仅此而已。因此,如果我们将手动硬编码的方式(ProxyFactory)学透了,基本上也就掌握了Spring AOP了,至于注解的形式,我们只需要再探究一下Advice如何获取以及匹配就可以了

剖去注解与Xml的配置,Spring AOP的核心就是ProxyFactory,抓住主线,才能更好的把握源码脉络,不至于被边角的细节所干扰

ProxyFactory代码示例

我们将会写一个UserService接口,定义findUser方法,同时在before跟after使用Advice(增强)对方法进行增强,最后使用ProxyFactory进行代理的生成。

接口:

public interface UserService {
	public void findUser();
}

实现类:

public class UserServiceImpl implements UserService {
	@Override
	public void findUser() {
		System.out.println("findUser...");
	}
}

2个增强:

// 前置增强
public class LogBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("before log...");
    }
}

// 后置增强
public class LogAfterAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("after log...");
    }
}

测试:

public class UserServiceImplImplTest {
    @Test
    public void findUser() {
        // 1. 创建代理工厂
        ProxyFactory factory = new ProxyFactory();
        // 2. 设置代理目标对象
        factory.setTarget(new UserServiceImpl());
        // 3. 设置接口 (可以多实现)
        factory.setInterfaces(new Class[]{UserService.class});
        // 4. 设置增强
        factory.addAdvice(new LogBeforeAdvice());
        factory.addAdvice(new LogAfterAdvice());
        // 5. 获取代理对象
        UserService userService = (UserService) factory.getProxy();

        userService.findUser();
    }
}

运行结果:

before log...
findUser...
after log...

Process finished with exit code 0

ProxyFactory继承关系

下面继承上面

ProxyFactory

我们重点关心一下类,忽略接口

  • ProxyConfig:用于保存Proxy的相关基础配置,比如是否使用激进模式optimize、强制开起cglib代理proxyTargetClass、是否暴露代理exposeProxy等,在xml配置中十分常见,例如<aop:aspectj-autoproxy proxy-target-class=“true”/>强制开启Cglib代理
  • AdvisedSupport:AOP的配置管理类,比起ProxyConfig,其还保存了targetSource(目标对象的封装)、切面的集合advisors、接口集合interfaces等
  • ProxyCreatorSupport:代理工厂的基础类,提供对可配置AopProxyFactory的便捷访问

这样代理工厂中就有了:目标对象+切面+接口+配置

ProxyFactory源码分析

下面依照上面测试中代码顺序依次分析

1 代理工厂

1 创建代理工厂,直接调用默认空构造器

ProxyFactory factory = new ProxyFactory();
2 目标对象

2 设置代理目标对象,将target对象封装成TargetSource对象,为什么要多此一举呢?其实封装为TargetSource的目的是为了做对象池和多例用的,也就是说每次代理都从池中获取对象。而这里我们只使用SingletonTargetSource,关于TargetSource留到后面讲解。刚刚提到这些属性都是保存在AdvisedSupport中的

// 2. 设置代理目标对象
factory.setTarget(new UserServiceImpl());
        

public void setTarget(Object target) {
    setTargetSource(new SingletonTargetSource(target));
}

@Override
public void setTargetSource(@Nullable TargetSource targetSource) {
    this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}
3 接口

3 设置接口数组,同样保存到AdvisedSupport的属性中

// 3. 设置接口 (可以多实现)
factory.setInterfaces(new Class[]{UserService.class});
        

public void setInterfaces(Class<?>... interfaces) {
    Assert.notNull(interfaces, "Interfaces must not be null");
    // 先清空再添加
    this.interfaces.clear();
    for (Class<?> ifc : interfaces) {
        addInterface(ifc);
    }
}
public void addInterface(Class<?> intf) {
    Assert.notNull(intf, "Interface must not be null");
    // 校验如果不是接口则抛出异常
    if (!intf.isInterface()) {
        throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
    }
    if (!this.interfaces.contains(intf)) {
        this.interfaces.add(intf);
        adviceChanged();
    }
}
4 通知

4 设置Advice,前面我们说过Advice只是增强,因此我们要封装成Advisor切面才能加到AdvisedSupport的advisors集合中。而需要注意的是因为没有配置任何的Pointcut,因此将使用DefaultPointcutAdvisor进行创建

// 4. 设置增强
factory.addAdvice(new LogBeforeAdvice());
//implements AfterReturningAdvice
factory.addAdvice(new LogAfterAdvice());


@Override
public void addAdvice(Advice advice) throws AopConfigException {
    int pos = this.advisors.size();
    addAdvice(pos, advice);
}
@Override
public void addAdvice(int pos, Advice advice) throws AopConfigException {
    Assert.notNull(advice, "Advice must not be null");

    if (advice instanceof IntroductionInfo) {
        // We don't need an IntroductionAdvisor for this kind of introduction:
        // It's fully self-describing.
        // 单独处理引介增强
        addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
    }
    else if (advice instanceof DynamicIntroductionAdvice) {
        // We need an IntroductionAdvisor for this kind of introduction.
        // DynamicIntroductionAdvice只能作为IntroductionAdvisor的一部分
        throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
    }
    else {
        // 普通增强
        addAdvisor(pos, new DefaultPointcutAdvisor(advice));
    }
}

@Override
public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
    if (advisor instanceof IntroductionAdvisor) {
        validateIntroductionAdvisor((IntroductionAdvisor) advisor);
    }
    addAdvisorInternal(pos, advisor);
}

private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
    Assert.notNull(advisor, "Advisor must not be null");
    if (isFrozen()) {
        throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
    }
    if (pos > this.advisors.size()) {
        throw new IllegalArgumentException(
            "Illegal position " + pos + " in advisor list with size " + this.advisors.size());
    }
    this.advisors.add(pos, advisor);
    updateAdvisorArray();
    adviceChanged();
}

而DefaultPointcutAdvisor的意思就是无论什么方法都匹配,因此可以看到Pointcut使用的是Pointcut.TRUE,无论匹配什么方法都是true

new DefaultPointcutAdvisor(advice)
// Pointcut.TRUE
// 也就是说该Advisor的匹配均为true,匹配任何的方法,不做任何限制!
public DefaultPointcutAdvisor(Advice advice) {
	this(Pointcut.TRUE, advice);
}
5代理

5 创建代理,这才是本篇的重头戏

// 5. 获取代理对象
UserService userService = (UserService) factory.getProxy();


public Object getProxy() {
    return createAopProxy().getProxy();
}

代码就createAopProxy().getProxy()一句,在调用getProxy()之前,我们得弄清楚是什么对象调用的getProxy(),换句话说,也就是createAopProxy()到底创建了什么对象

  • UserService userService = (UserService) factory.getProxy();
    • factory.getProxy(){ createAopProxy().getProxy(); }
      • createAopProxy() :给工厂传入代理配置
        • getAopProxyFactory().createAopProxy(this);
          • getAopProxyFactory():返回this.aopProxyFactory;
          • createAopProxy(this):判断进行jdk动态代理还是cglib代理
      • getProxy():创建代理对象
protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
    // 先获取工厂,再创建代理 // 传入工厂
	return getAopProxyFactory().createAopProxy(this);
}
---------------------------------------------------------
public AopProxyFactory getAopProxyFactory() {
	// 返回的是类中的成员变量aopProxyFactory
	return this.aopProxyFactory;
}
---------------------------------------------------------
// 成员变量的实例化则是在默认构造器中
private AopProxyFactory aopProxyFactory;

// 构造器,调用了DefaultAopProxyFactory进行实例化,因此aopProxyFactory真正的类型是DefaultAopProxyFactory
public ProxyCreatorSupport() {
	this.aopProxyFactory = new DefaultAopProxyFactory();
}

跟踪发现createAopProxy()返回的是属性aopProxyFactory,而属性aopProxyFactory又是在ProxyCreatorSupport构造器时进行实例化的,真正的类是DefaultAopProxyFactory,因此继续跟踪DefaultAopProxyFactory的createAopProxy方法

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    // 利用工厂创建代理 
    @Override// 传入的config是工厂,工厂的父类中有代理的各种信息
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // isOptimize开启激进模式 || proxyTargetClass=true(强制开启cglib代理) || 接口集合为空
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                                             "Either an interface or a target is required for proxy creation.");
            }
            // 目标对象为接口,一般不会发生
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                return new JdkDynamicAopProxy(config);
            }
            // 没有接口,只能选择cglib代理
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            // 使用JDK代理
            return new JdkDynamicAopProxy(config);
        }
    }
    ...
}

可以看到,当config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)为真时才会使用Cglib代理,而当代理对象有实现接口,并且没有强制开启cglib代理时默认使用的是JDK代理,也就是JdkDynamicAopProxy类。

也就是说,最后将调用的其实是new JdkDynamicAopProxy(config).getProxy(),结合Jdk动态代理底层源码的内容,可以预想到有2个需要特别关注的方法。getProxy和invoke方法

// JdkDynamicAopProxy.java
@Override // 创建代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    // 获取代理接口
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    // 判断接口是否又hashCode和equals方法
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // 使用JDK代理(classLoader, 接口, 当前JdkDynamicAopProxy对象:用于回调invoke和target对象方法)
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
  • createAopProxy是创建好代理的各种信息
  • getProxy是创建代理对象

可以看出,其实每个知识点都是关联在一起的,ProxyFactory作为Spring AOP的核心,使用的也是我们学习过的Jdk动态代理来实现的。结合第一篇Jdk动态代理底层源码的内容,最最重要的便是getProxy和invoke方法,下一节我们将进行JdkDynamicAopProxy中getProxy和invoke方法的源码剖析

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值