Spring 中的 ProxyFactory 创建代理对象

一、jdk 动态代理 和 cglib动态代理 简单介绍 

        1.jdk动态代理

public interface AService {
    public String serviceA(String param);
    public String serviceAA(String param);
}
public interface BService {
    public String serviceB(String param);
    public String serviceBB(String param);
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class JdkCustomInvocationHandler implements InvocationHandler {

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

        if(method.equals(AService.class.getMethod("serviceA" , String.class))){
            // 在这里可以写 当我们把代理当作 AService 的实现子类,调用 serviceA 方法时
            // 我们要执行的代码,这里我们姑且就简单打印,并返回一个值
            System.out.println("JdkCustomInvocationHandler 开始处理 com.fll.start.dynamic_proxy.jdk.AService.serviceA 方法");
            return "JdkCustomInvocationHandler 处理 com.fll.start.dynamic_proxy.jdk.BService.serviceA 的结果";
        }else if(method.equals(BService.class.getMethod("serviceB", String.class))){
            // 在这里可以写 当我们把代理当作 BService 的实现子类,调用 serviceB 方法时
            // 我们要执行的代码,这里我们姑且就简单打印,并返回一个值
            System.out.println("JdkCustomInvocationHandler 开始处理 com.fll.start.dynamic_proxy.jdk.BService.serviceB 方法");
            return "JdkCustomInvocationHandler 处理 com.fll.start.dynamic_proxy.jdk.BService.serviceB 的结果";
        }else {
            return "暂时对该方法没有处理逻辑";
        }

    }
}

这里总结下jdk动态代理的特点:
        1.可以不需要实现类,直接对接口进行代理
        2.创建代理对象时返回的类型时Object,但是可以将其强转为任何一个它所代理的接口类型
因为生成的代理对象是它所代理的所有接口的实现类
        3.当我们将代理对象强转为它所代理的接口类型进行方法调用时,所有的调用都会回调到InvocationHandler 对象的 invoke 方法,在回调 invoke 方法的参数中有我们调用的方法对象 Method method,和调用时所传递的所有参数Object[] objects,Object o就是代理对象本身
        4.关于这几个参数的注意点
                1.不能在 invoke 方法中将代理对象强转为它所代理的某一个接口,然后调用其方法,这          样会形成递归调用,造成栈内存溢出
                2.如果没有所代理的接口的真正实现类,不可以通过反射的方法调用该方法,因为通过            反射的方式,Method.invoke() 方法进行调用时,需要传递真正实现了该接口的实现类的一个          对象,这里的Object o对象虽然也是接口的实现类的对象,但是不能传递 o ,如果过传递                o,还是相当于调用了代理对象的方法,也会形成递归调用。
                3.要想让代理对象调用不同的方法时,分别执行我们想要的逻辑,只能在 invoke 方法的          回调中通过判断 Method method 对象的不同,执行不同业务逻辑
        5.这样的的代理方式没啥实际意义,只是把对所有接口方法的调用全部回调到了 InvocationHandler.invoke() 方法中,在invoke中进行分别实现,会造成代码冗长杂乱

 接下来常规用法

public class AServiceImpl implements AService{
    @Override
    public String serviceA(String param){
        System.out.println("AServiceImpl 开始执行 serviceA,param=" + param);
        return "AServiceImpl.serviceA 处理的结果";
    }
    @Override
    public String serviceAA(String param) {
        System.out.println("AServiceImpl 开始执行 serviceAA,param=" + param);
        return "AServiceImpl.serviceAA 处理的结果";
    }
}
public class BServiceImpl implements BService{
    @Override
    public String serviceB(String param){
        System.out.println("BServiceImpl 开始执行 serviceB,param=" + param);
        return "BServiceImpl.serviceB 处理的结果";
    }
    @Override
    public String serviceBB(String param) {
        System.out.println("BServiceImpl 开始执行 serviceBB,param=" + param);
        return "BServiceImpl.serviceBB 处理的结果";
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class JdkCustomInvocationHandler1 implements InvocationHandler {

    private AService aService;
    private BService bService;

    public JdkCustomInvocationHandler1(AService aService , BService bService){
        this.aService = aService;
        this.bService = bService;
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

        if(method.equals(AService.class.getMethod("serviceA" , String.class))){
            System.out.println(String.format("执行%s前置加强逻辑" , aService.getClass() +"."+ method.getName()));
            Object retVal = method.invoke(this.aService , objects);
            System.out.println(String.format("执行%s后置加强逻辑" , aService.getClass() +"."+ method.getName()));
            return retVal + "(也可以被代理对象再加工)";
        }else if(method.equals(BService.class.getMethod("serviceB", String.class))){
            System.out.println(String.format("执行%s前置加强逻辑" , bService.getClass() +"."+ method.getName()));
            Object retVal = method.invoke(this.bService , objects);
            System.out.println(String.format("执行%s后置加强逻辑" , bService.getClass() +"."+ method.getName()));
            return retVal + "(也可以被代理对象再加工)";
        }else {
            return "暂时对该方法没有处理逻辑";
        }

    }
}
public class JdkDynamicProxyTest1 {


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

        ClassLoader classLoader = JdkDynamicProxyTest1.class.getClassLoader();
        Class[] interfaces = {AService.class, BService.class};

        AService aService = new AServiceImpl();
        BService bService = new BServiceImpl();
        JdkCustomInvocationHandler1 jdkCustomInvocationHandler
                = new JdkCustomInvocationHandler1(aService , bService);

        AService aServiceProxy = (AService) Proxy.newProxyInstance(classLoader, interfaces, jdkCustomInvocationHandler);
        String test = aServiceProxy.serviceA("AService");
        System.out.println(test);

        System.out.println();

        BService bServiceProxy = (BService) Proxy.newProxyInstance(classLoader , interfaces , jdkCustomInvocationHandler);
        String test1 = bServiceProxy.serviceB("BService");
        System.out.println(test1);


    }

}

运行结果:
执行class com.fll.start.dynamic_proxy.jdk.AServiceImpl.serviceA前置加强逻辑
AServiceImpl 开始执行 serviceA,param=AService
执行class com.fll.start.dynamic_proxy.jdk.AServiceImpl.serviceA后置加强逻辑
AServiceImpl.serviceA 处理的结果(也可以被代理对象再加工)

执行class com.fll.start.dynamic_proxy.jdk.BServiceImpl.serviceB前置加强逻辑
BServiceImpl 开始执行 serviceB,param=BService
执行class com.fll.start.dynamic_proxy.jdk.BServiceImpl.serviceB后置加强逻辑
BServiceImpl.serviceB 处理的结果(也可以被代理对象再加工)

          这次的特点:
                1.所代理的接口本来就有自己的实现类
                2.调用所代理的接口的方法时,最终都会在 InvocationHandler.invoke() 方法中通过反射           的方式调用到接口实现类对象的对应方法上,只不过我们可以在调用实现类方法之前或者之           后执行额外的逻辑,进行加强,也可以对实现类返回的结果进行再加工

        其实这种方式才是代理模式要达到的真正目的,本来就有实现好的功能,而且代码运行稳定,或者说一个黑盒子,我们只知道其功能和参数,这些情况下,我们想要对原本的功能或者黑盒子进行加强,但是又不想修改原来代码逻辑,所以就可以通过代理,在原来的功能之上 ,进行额外的加强处理

 通过jdk源码,看看代理对象是如何创建的
java.lang.reflect.Proxy#newProxyInstance

/**
 * Returns an instance of a proxy class for the specified interfaces
 * that dispatches method invocations to the specified invocation
 * handler.
 *
 * <p>{@code Proxy.newProxyInstance} throws
 * {@code IllegalArgumentException} for the same reasons that
 * {@code Proxy.getProxyClass} does.
 *
 * @param   loader the class loader to define the proxy class
 * @param   interfaces the list of interfaces for the proxy class
 *          to implement
 * @param   h the invocation handler to dispatch method invocations to
 * @return  a proxy instance with the specified invocation handler of a
 *          proxy class that is defined by the specified class loader
 *          and that implements the specified interfaces
 * @throws  IllegalArgumentException if any of the restrictions on the
 *          parameters that may be passed to {@code getProxyClass}
 *          are violated
 * @throws  SecurityException if a security manager, <em>s</em>, is present
 *          and any of the following conditions is met:
 *          <ul>
 *          <li> the given {@code loader} is {@code null} and
 *               the caller's class loader is not {@code null} and the
 *               invocation of {@link SecurityManager#checkPermission
 *               s.checkPermission} with
 *               {@code RuntimePermission("getClassLoader")} permission
 *               denies access;</li>
 *          <li> for each proxy interface, {@code intf},
 *               the caller's class loader is not the same as or an
 *               ancestor of the class loader for {@code intf} and
 *               invocation of {@link SecurityManager#checkPackageAccess
 *               s.checkPackageAccess()} denies access to {@code intf};</li>
 *          <li> any of the given proxy interfaces is non-public and the
 *               caller class is not in the same {@linkplain Package runtime package}
 *               as the non-public interface and the invocation of
 *               {@link SecurityManager#checkPermission s.checkPermission} with
 *               {@code ReflectPermission("newProxyInPackage.{package name}")}
 *               permission denies access.</li>
 *          </ul>
 * @throws  NullPointerException if the {@code interfaces} array
 *          argument or any of its elements are {@code null}, or
 *          if the invocation handler, {@code h}, is
 *          {@code null}
 */
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)throws IllegalArgumentException{

    Objects.requireNonNull(h);

    final Class<?>[] intfs = interfaces.clone();
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }

    /* 
     * 生成代理类的 Class 对象
     * Look up or generate the designated proxy class.
     */
    Class<?> cl = getProxyClass0(loader, intfs);

    /*
     * Invoke its constructor with the designated invocation handler.
     */
    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }
        // 这里的private static final Class<?>[] constructorParams =
        // {InvocationHandler.class };
        // 通过代理类的 Class 对象获取参数为 InvocationHandler 对象的构造器对象
        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;
                }
            });
        }
        // 通过代理类构造器对象创一个 代理类的对象
        return cons.newInstance(new Object[]{h});
    } 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);
    }
}

java.lang.reflect.Proxy#getProxyClass0 

/**
 * Generate a proxy class.  Must call the checkProxyAccess method
 * to perform permission checks before calling this.
 */
private static Class<?> getProxyClass0(ClassLoader loader,
                                       Class<?>... interfaces) {
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }

    // If the proxy class defined by the given loader implementing
    // the given interfaces exists, this will simply return the cached copy;
    // otherwise, it will create the proxy class via the ProxyClassFactory
    // 如果被指定的类加载器定义好的,实现了指定接口的代理类 Class 对象已经存在了
    // 那就简单的返回缓存中的备份,相反如果不存在,就得通过ProxyClassFactory创建
    // 代理类的 Class 对象,并放入缓存中
    return proxyClassCache.get(loader, interfaces);
}

 java.lang.reflect.WeakCache#get

/**
 * Look-up the value through the cache. This always evaluates the
 * {@code subKeyFactory} function and optionally evaluates
 * {@code valueFactory} function if there is no entry in the cache for given
 * pair of (key, subKey) or the entry has already been cleared.
 *
 * @param key       possibly null key
 * @param parameter parameter used together with key to create sub-key and
 *                  value (should not be null)
 * @return the cached value (never null)
 * @throws NullPointerException if {@code parameter} passed in or
 *                              {@code sub-key} calculated by
 *                              {@code subKeyFactory} or {@code value}
 *                              calculated by {@code valueFactory} is null.
 */
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);
	
    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

	//
    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
	// 生成代理类Class对象的主要逻辑在 subKeyFactory.apply(key, parameter)
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            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)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            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);
            }
        }
    }
}

 java.lang.reflect.Proxy.ProxyClassFactory#apply

/**
 * A factory function that generates, defines and returns the proxy class given
 * the ClassLoader and array of interfaces.
 */
private static final class ProxyClassFactory
    implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
    // prefix for all proxy class names
    private static final String proxyClassNamePrefix = "$Proxy";

    // next number to use for generation of unique proxy class names
    private static final AtomicLong nextUniqueNumber = new AtomicLong();

    @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

        Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
        for (Class<?> intf : interfaces) {
            /*
             * Verify that the class loader resolves the name of this
             * interface to the same Class object.
             */
            Class<?> interfaceClass = null;
            try {
                interfaceClass = Class.forName(intf.getName(), false, loader);
            } catch (ClassNotFoundException e) {
            }
            if (interfaceClass != intf) {
                throw new IllegalArgumentException(
                    intf + " is not visible from class loader");
            }
            /*
             * Verify that the Class object actually represents an
             * interface.
             */
            if (!interfaceClass.isInterface()) {
                throw new IllegalArgumentException(
                    interfaceClass.getName() + " is not an interface");
            }
            /*
             * Verify that this interface is not a duplicate.
             */
            if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                throw new IllegalArgumentException(
                    "repeated interface: " + interfaceClass.getName());
            }
        }

        String proxyPkg = null;     // package to define proxy class in
        int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

        /*
         * Record the package of a non-public proxy interface so that the
         * proxy class will be defined in the same package.  Verify that
         * all non-public proxy interfaces are in the same package.
         */
        for (Class<?> intf : interfaces) {
            int flags = intf.getModifiers();
            if (!Modifier.isPublic(flags)) {
                accessFlags = Modifier.FINAL;
                String name = intf.getName();
                int n = name.lastIndexOf('.');
                String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                if (proxyPkg == null) {
                    proxyPkg = pkg;
                } else if (!pkg.equals(proxyPkg)) {
                    throw new IllegalArgumentException(
                        "non-public interfaces from different packages");
                }
            }
        }

        if (proxyPkg == null) {
            // if no non-public proxy interfaces, use com.sun.proxy package
            proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }

        /*
         * Choose a name for the proxy class to generate.
         */
        long num = nextUniqueNumber.getAndIncrement();
        String proxyName = proxyPkg + proxyClassNamePrefix + num;

        /*
         * Generate the specified proxy class.
         * 生成代理类,我们看到生成代理类Class对象需要两部
         * 1.生成一个字节数组,其实等价于我们通过.class文件创建Class对象的时候,把.class文件            
         * 加载进内存,放到一个字节数组中
         * 2.通过 defineClass0() 方法把字节数组解析为一个Class对象
         */
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
            proxyName, interfaces, accessFlags);
        try {
            return defineClass0(loader, proxyName,
                                proxyClassFile, 0, proxyClassFile.length);
        } catch (ClassFormatError e) {
            /*
             * A ClassFormatError here means that (barring bugs in the
             * proxy class generation code) there was some other
             * invalid aspect of the arguments supplied to the proxy
             * class creation (such as virtual machine limitations
             * exceeded).
             */
            throw new IllegalArgumentException(e.toString());
        }
    }
}

 我们看到可以通过以下代码生成一个等价于.class文件的字节数组,那我们把生成的这个字节数组输出到一个文件,是不是就相当于得到了这个代理类的 .class 文件了

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
            proxyName, interfaces, accessFlags);
import sun.misc.ProxyGenerator;

import java.io.IOException;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ProxyGeneratorTest {

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

        ClassLoader classLoader = JdkDynamicProxyTest1.class.getClassLoader();
        Class[] interfaces = {AService.class, BService.class};

        AService aService = new AServiceImpl();
        BService bService = new BServiceImpl();
        JdkCustomInvocationHandler1 jdkCustomInvocationHandler
                = new JdkCustomInvocationHandler1(aService , bService);

        Object proxyInstance = Proxy.newProxyInstance(classLoader, interfaces, jdkCustomInvocationHandler);

        byte[] bytes = ProxyGenerator.generateProxyClass(proxyInstance.getClass().getSimpleName(), interfaces);
        Files.write(Paths.get("D:/springboot-demo/study-spring/src/main/java/com/fll/start/dynamic_proxy/jdk/" + proxyInstance.getClass().getSimpleName() + ".class") , bytes);

    }

}

 以下是使用idea将生成的.class文件反编译之后得到的源码

import com.fll.start.dynamic_proxy.jdk.AService;
import com.fll.start.dynamic_proxy.jdk.BService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements AService, BService {
    private static Method m1;
    private static Method m4;
    private static Method m2;
    private static Method m6;
    private static Method m3;
    private static Method m0;
    private static Method m5;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    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 serviceA(String var1) throws  {
        try {
            return (String)super.h.invoke(this, m4, new Object[]{var1});
        } 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 String serviceBB(String var1) throws  {
        try {
            return (String)super.h.invoke(this, m6, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

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

    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);
        }
    }

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

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m4 = Class.forName("com.fll.start.dynamic_proxy.jdk.AService").getMethod("serviceA", Class.forName("java.lang.String"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m6 = Class.forName("com.fll.start.dynamic_proxy.jdk.BService").getMethod("serviceBB", Class.forName("java.lang.String"));
            m3 = Class.forName("com.fll.start.dynamic_proxy.jdk.AService").getMethod("serviceAA", Class.forName("java.lang.String"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m5 = Class.forName("com.fll.start.dynamic_proxy.jdk.BService").getMethod("serviceB", Class.forName("java.lang.String"));
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

这里注意最好用 jdk1.8,在jdk11 中,这个方法就不是public了,测试调用的话比较麻烦 

可以看到这里的代理类 除了实现了 我们要代理的接口 AService, BService之外还结成了java.lang.reflect.Proxy,我们使用代理类的构造器创建代理对象时,所传的 构造器参数InvocationHandler 就是通过 super(InvocationHandler) 传到了java.lang.reflect.Proxy

        2.cglib动态代理

public class CustomCglibMethodInterceptor<T> implements MethodInterceptor {

    private T target;

    public CustomCglibMethodInterceptor(T target){
        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println(String.format("执行%s前置加强逻辑" , target.getClass() +"."+ method.getName()));
        Object invoke = method.invoke(target, objects);
        methodProxy.invoke(target , objects);
        System.out.println(String.format("执行%s后置加强逻辑" , target.getClass() +"."+ method.getName()));
        return invoke + "(也可以被代理对象再加工)";
    }

}
public class CglibDynamicProxyTest {

    public static void main(String[] args) {

        AService aService = new AServiceImpl();

        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(aService.getClass());
//        enhancer.setSuperclass(AService.class);
        enhancer.setCallback(new CustomCglibMethodInterceptor(aService));

        AService aServiceProxy = (AService) enhancer.create();

        String s = aServiceProxy.serviceA("test-serviceA");

        System.out.println(s);


    }

}

运行结果:
执行class com.fll.start.dynamic_proxy.AServiceImpl.serviceA前置加强逻辑
AServiceImpl 开始执行 serviceA,param=test-serviceA
AServiceImpl 开始执行 serviceA,param=test-serviceA
执行class com.fll.start.dynamic_proxy.AServiceImpl.serviceA后置加强逻辑
AServiceImpl.serviceA 处理的结果(也可以被代理对象再加工)

        总结一下 cglib 动态代理的特点:

                1. cglib既能代理接口,又能代理实现类
                2. 如果代理的时接口,那么生成的代理类就会实现该接口,如果代理的时实现类,那么         生成代理类就会继承该类,由于java的类之间只支持单继承,所以一个 cglib 代理类只能代理         一个接口,或者代理一个实现类
                3. 在 cglib 的MethodInterceptor 实现类中,调用目标对象的有两种方法                                            method.invoke(target, objects);
                methodProxy.invoke(target , objects);

那么 cglib 的原理是什么呢,我们能不能也想上面反编译jdk动态代理类字节码一样,反编译一下cglib的代理类的字节码呢,我自己想了个办法还是成功反编译了
org.springframework.cglib.core.AbstractClassGenerator#generate

protected Class generate(ClassLoaderData data) {
		Class gen;
		Object save = CURRENT.get();
		CURRENT.set(this);
		try {
			ClassLoader classLoader = data.getClassLoader();
			if (classLoader == null) {
				throw new IllegalStateException("ClassLoader is null while trying to define class " +
						getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
						"Please file an issue at cglib's issue tracker.");
			}
			synchronized (classLoader) {
				String name = generateClassName(data.getUniqueNamePredicate());
				data.reserveName(name);
				this.setClassName(name);
			}
			if (attemptLoad) {
				try {
					gen = classLoader.loadClass(getClassName());
					return gen;
				}
				catch (ClassNotFoundException e) {
					// ignore
				}
			}
			byte[] b = strategy.generate(this);
			String className = ClassNameReader.getClassName(new ClassReader(b));
			ProtectionDomain protectionDomain = getProtectionDomain();
			synchronized (classLoader) { // just in case
				// SPRING PATCH BEGIN
				gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass);
				// SPRING PATCH END
			}
			return gen;
		}
		catch (RuntimeException | Error ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CodeGenerationException(ex);
		}
		finally {
			CURRENT.set(save);
		}
	}

Files.write(Paths.get("D:/springboot-demo/study-spring/src/main/java/com/fll/start/dynamic_proxy/cglib/" + "AServiceImpl$$EnhancerByCGLIB$$bfa5b612.class") , b) 

我们可以看到Files 和 Paths 都爆红,可以想正常写代码那样导入包就行了

解决了报错之后,直接点击右下角的 Evaluate 就可以了,然后刷新一下你输出的包,就会出现你输出的 .class 文件

 使用 idea 打开就可以看到反编译后的代理类源码

package com.fll.start.dynamic_proxy;

import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class AServiceImpl$$EnhancerByCGLIB$$bfa5b612 extends AServiceImpl implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    private MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$serviceA$0$Method;
    private static final MethodProxy CGLIB$serviceA$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$serviceAA$1$Method;
    private static final MethodProxy CGLIB$serviceAA$1$Proxy;
    private static final Method CGLIB$equals$2$Method;
    private static final MethodProxy CGLIB$equals$2$Proxy;
    private static final Method CGLIB$toString$3$Method;
    private static final MethodProxy CGLIB$toString$3$Proxy;
    private static final Method CGLIB$hashCode$4$Method;
    private static final MethodProxy CGLIB$hashCode$4$Proxy;
    private static final Method CGLIB$clone$5$Method;
    private static final MethodProxy CGLIB$clone$5$Proxy;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.fll.start.dynamic_proxy.AServiceImpl$$EnhancerByCGLIB$$bfa5b612");
        Class var1;
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$2$Method = var10000[0];
        CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
        CGLIB$toString$3$Method = var10000[1];
        CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
        CGLIB$hashCode$4$Method = var10000[2];
        CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
        CGLIB$clone$5$Method = var10000[3];
        CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
        var10000 = ReflectUtils.findMethods(new String[]{"serviceA", "(Ljava/lang/String;)Ljava/lang/String;", "serviceAA", "(Ljava/lang/String;)Ljava/lang/String;"}, (var1 = Class.forName("com.fll.start.dynamic_proxy.AServiceImpl")).getDeclaredMethods());
        CGLIB$serviceA$0$Method = var10000[0];
        CGLIB$serviceA$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "serviceA", "CGLIB$serviceA$0");
        CGLIB$serviceAA$1$Method = var10000[1];
        CGLIB$serviceAA$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "serviceAA", "CGLIB$serviceAA$1");
    }

    final String CGLIB$serviceA$0(String var1) {
        return super.serviceA(var1);
    }

    public final String serviceA(String var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$serviceA$0$Method, new Object[]{var1}, CGLIB$serviceA$0$Proxy) : super.serviceA(var1);
    }

    final String CGLIB$serviceAA$1(String var1) {
        return super.serviceAA(var1);
    }

    public final String serviceAA(String var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$serviceAA$1$Method, new Object[]{var1}, CGLIB$serviceAA$1$Proxy) : super.serviceAA(var1);
    }

    final boolean CGLIB$equals$2(Object var1) {
        return super.equals(var1);
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

    final String CGLIB$toString$3() {
        return super.toString();
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
    }

    final int CGLIB$hashCode$4() {
        return super.hashCode();
    }

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

    final Object CGLIB$clone$5() throws CloneNotSupportedException {
        return super.clone();
    }

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? var10000.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
    }

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -2021511251:
            if (var10000.equals("serviceA(Ljava/lang/String;)Ljava/lang/String;")) {
                return CGLIB$serviceA$0$Proxy;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$5$Proxy;
            }
            break;
        case 386645590:
            if (var10000.equals("serviceAA(Ljava/lang/String;)Ljava/lang/String;")) {
                return CGLIB$serviceAA$1$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$2$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$3$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$4$Proxy;
            }
        }

        return null;
    }

    public AServiceImpl$$EnhancerByCGLIB$$bfa5b612() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

    public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
        CGLIB$STATIC_CALLBACKS = var0;
    }

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        AServiceImpl$$EnhancerByCGLIB$$bfa5b612 var1 = (AServiceImpl$$EnhancerByCGLIB$$bfa5b612)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        AServiceImpl$$EnhancerByCGLIB$$bfa5b612 var10000 = new AServiceImpl$$EnhancerByCGLIB$$bfa5b612();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        AServiceImpl$$EnhancerByCGLIB$$bfa5b612 var10000 = new AServiceImpl$$EnhancerByCGLIB$$bfa5b612();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        AServiceImpl$$EnhancerByCGLIB$$bfa5b612 var10000 = new AServiceImpl$$EnhancerByCGLIB$$bfa5b612;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }

        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }

    public Callback[] getCallbacks() {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

 可以看到 cglib 的代理类源码 和 jdk 动态代理的 代理类源码 实现原理都差不多,都是先把被代理的类或者被代理接口所有的方法的 Method 对象取出来作为代理类的成员变量,当调用代理类的对应方法时,就在成员变量中找到对应的 Method 对象 和 和传进来的参数,一起调用一个 回调方法,这个回调方法是我们自己实现的,所以我们可以在回调方法中按照自己的想法来实现

二、Spring中的 三个重要的概念 Advice  Advisor  Advised

        1.Advice

         Advice 是AOP中的核心概念之一,它定义了在特定的连接点(Join point)上执行的行为。简单来说,Advice 就是你希望在方法调用前、后、异常抛出时等不同时机下执行的代码。Spring AOP 支持多种类型的 Advice,包括但不限于:

Before advice:在方法调用之前执行的通知。
After returning advice:在方法成功返回结果之后执行的通知。
After throwing advice:在方法抛出异常之后执行的通知。
After (finally) advice:无论方法是否正常完成,都会执行的通知。
Around advice:包围方法调用的通知,可以控制方法是否执行以及何时执行

        2.Pointcut

        Pointcut定义了在何处应用通知(Advice)。它指定了程序执行过程中的一个或多个连接点(JoinPoint),在这些连接点上将执行特定的通知。

        Pointcut用于定义切入点集合,即哪些连接点会被拦截。
        它可以是一个具体的方法、一组方法、类中的所有方法、包中的所有方法等。
        Pointcut可以使用表达式来定义,例如使用AspectJ的切点表达式。

        Pointcut可以理解为一个连接点的过滤规则,我们定义的每个方法都有做为连接点的可能,但          是最后哪些方法会成为我们想要添加额外的 Advice 的方法呢,这就需要具体的 Pointcut 实            现进行过滤,针对包名过滤,针对类名过滤,针对方法名过滤。这种过滤不一定是相等比较
        ,也可以是通过一个正则表达式进行匹配

        3.JoinPoint

        JoinPoint可以理解为Pointcut筛选出来的一个具体的执行点(也就是要被加强的那些方法),在这个点上要执行额外的Advice逻辑,只要满足Pointcut规则的方法都可以成为JoinPoint,在执行Advice逻辑的时候,JoinPoint会作为参数被传到Advice方法中,作为执行Advice的上下文,我们在Advice方法中通过JoinPoint获取到要被加强的方法的所有信息,包括 Method对象,参数,返回值

通过 Pointcut,你可以精确地控制 Advice 的应用范围,而 JoinPoint 则提供了在 Advice 中访问当前执行点信息的能力。两者共同作用,使得Spring AOP能够灵活地实现横切关注点的管理。

        4.Advisor

Advisor 可以看作是 Advice 的封装,它不仅包含了 Advice,还可能包含一个切入点(Pointcut),用于指定 Advice 应该应用到哪些连接点。如果一个 Advisor 没有指定切入点,那么它的 Advice 将被应用到所有连接点。常见的 Advisor 类型有:

DefaultPointcutAdvisor:最常用的 Advisor,允许同时指定一个切入点和一个通知。
RegexpMethodPointcutAdvisor:基于正则表达式匹配方法名来确定切入点,默认是 JdkRegexpMethodPointcut。
NameMatchMethodPointcutAdvisor:根据方法名称匹配来确定切入点。
AspectJExpressionPointcutAdvisor: 根据AspectJ表达式匹配包名,类名,方法名

        5.Advised

这个接口稍微复杂点,这里举个例子说明一下,便于自己以后看的时候好理解,好回忆。
就以jdk动态代理为例,在创建 jdk 动态代理的时候,需要传递一个InvocationHandler的实现类对象,和被代理的接口数组。当我们将代理对象转换为被代理的某一个接口类型 UserService,调用其方法时 addUser(User user),就会回调我们创建代理对象时传递的那个 InvocationHandler 对象的 invoke 方法。回调 invoke(Object proxy, Method method, Object[] args)时,代理对象会传递要调用的目标方法Method method,和实际调用代理对象时传的参数。我们可以在 invoke() 方法对被代理接口的一个实现类 UserServiceImpl 的对象进行加强。要对 UserServiceImpl 的对象进行加强我们有几个需求要满足:

        1.需要被加强的 UserServiceImpl 实例
        2.需要除了 UserServiceImpl.addUser(User user) 自己的业务以外,额外添加的加强行为Advice,这里可以添加多个Advice
        3.需要一个组件能够根据配置,判断有哪些Advice需要被应用到当前方法Method来对其进行加强,其实Advisor可以解决2和3这两个问题,因为Advisor同时封装可 Pointcut 和 Advice

所以在创建 InvocationHandler 实例的时候,就需要把这些信息传给这个 InvocationHandler 的实例,这样在回调到它的 invoke 方法的时候,他就能获取到这些信息了
Spring Aop 中创造代理时传的 InvocationHandler 实现类是 JdkDynamicAopProxy 构造函数

/**
 * Construct a new JdkDynamicAopProxy for the given AOP configuration.
 * @param config the AOP configuration as AdvisedSupport object
 * @throws AopConfigException if the config is invalid. We try to throw an informative
 * exception in this case, rather than let a mysterious failure happen later.
 */
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
	Assert.notNull(config, "AdvisedSupport must not be null");
	if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
		throw new AopConfigException("No advisors and no TargetSource specified");
	}
	this.advised = config;
	this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}

 构造参数传的是一个 AdvisedSupport 的对象,说明这个对象能解决我上面提出的三个需求

/**
 * Implementation of {@code InvocationHandler.invoke}.
 * <p>Callers will see exactly the exception thrown by the target,
 * unless a hook method throws an exception.
 */
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;

	TargetSource targetSource = this.advised.targetSource;
	Object target = null;

	try {
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			// The target does not implement the equals(Object) method itself.
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			// The target does not implement the hashCode() method itself.
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			// There is only getDecoratedClass() declared -> dispatch to proxy config.
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			// Service invocations on ProxyConfig with the proxy config...
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;

		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		// Get as late as possible to minimize the time we "own" the target,
		// in case it comes from a pool.
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		// Get the interception chain for this method.
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		// Check whether we have any advice. If we don't, we can fallback on direct
		// reflective invocation of the target, and avoid creating a MethodInvocation.
		if (chain.isEmpty()) {
			// We can skip creating a MethodInvocation: just invoke the target directly
			// Note that the final invoker must be an InvokerInterceptor so we know it does
			// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// We need to create a method invocation...
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			// Proceed to the joinpoint through the interceptor chain.
			retVal = invocation.proceed();
		}

		// Massage return value if necessary.
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target &&
				returnType != Object.class && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			// Special case: it returned "this" and the return type of the method
			// is type-compatible. Note that we can't help if the target sets
			// a reference to itself in another returned object.
			retVal = proxy;
		}
		else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException(
					"Null return value from advice does not match primitive return type for: " + method);
		}
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

 我们看到在 invoke 方法中,通过 this.advised 这个 AdvisedSupport 对象确实解决了了我们上面提到的三个需求

1.获取被加强的实例
TargetSource targetSource = this.advised.targetSource;
Object target = null;
target = targetSource.getTarget();
2.获取需要被应用到当前Method的 Advice,这里把需要应用到当前Method的Advice封装成了不同的MethodInterceptor 实现类对象。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
这里其实就解决了上面的 2,3 两个需求,说明 advised 也包含获取到要创建的代理对象需要用的所有Advisor
3.在invoke方法中发现,还从advised对象中获取了其他的一些配置信息
4.在下面创建代理对象的时候,传入的需要被代理的接口数组也是构造方法中从advised中解析出来的
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

 这样看来Advised其实就是一个配置信息管理类,可以配置管理 1.被代理的对象(被加强的对象),2.Advisor(用来获取当前被调的方法需要被额外加强的Advice) 3.被代理的接口数组(创建代理对象时需要) 4.另外在其他地方也有用到 AdvisedSupport 的其他配置,比如,proxyTargetClass,optimize,opaque,exposeProxy 其实这些属性是AdvisedSupport从ProxyConfig继承来的

这么看来AdvisedSupport是综合了 Advised 和 ProxyConfig 的更强大的配置类,Advised提供了target和Advisor配置和管理,ProxyConfig提供了proxyTargetClass,optimize,opaque,exposeProxy等的配置和管理

三、ProxyFactory 类的继承结构,以及每一层中实现的功能

 ProxyFactory 这一层自己没有定义任何属性,可以通过在构造方法中调用父类AdvisedSupport的配置方法,配置代理目标targetSource, 被代理的接口 proxyInterfaces,Advice


/**
 * Base class for proxy factories.
 * Provides convenient access to a configurable AopProxyFactory.
 *
 * @author Juergen Hoeller
 * @since 2.0.3
 * @see #createAopProxy()
 */
@SuppressWarnings("serial")
public class ProxyCreatorSupport extends AdvisedSupport {

	private AopProxyFactory aopProxyFactory;

	private final List<AdvisedSupportListener> listeners = new ArrayList<>();

	/** Set to true when the first AOP proxy has been created. */
	private boolean active = false;


	/**
	 * Create a new ProxyCreatorSupport instance.
	 */
	public ProxyCreatorSupport() {
		this.aopProxyFactory = new DefaultAopProxyFactory();
	}

	/**
	 * Create a new ProxyCreatorSupport instance.
	 * @param aopProxyFactory the AopProxyFactory to use
	 */
	public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
		Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
		this.aopProxyFactory = aopProxyFactory;
	}


	/**
	 * Customize the AopProxyFactory, allowing different strategies
	 * to be dropped in without changing the core framework.
	 * <p>Default is {@link DefaultAopProxyFactory}, using dynamic JDK
	 * proxies or CGLIB proxies based on the requirements.
	 */
	public void setAopProxyFactory(AopProxyFactory aopProxyFactory) {
		Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
		this.aopProxyFactory = aopProxyFactory;
	}

	/**
	 * Return the AopProxyFactory that this ProxyConfig uses.
	 */
	public AopProxyFactory getAopProxyFactory() {
		return this.aopProxyFactory;
	}

	/**
	 * Add the given AdvisedSupportListener to this proxy configuration.
	 * @param listener the listener to register
	 */
	public void addListener(AdvisedSupportListener listener) {
		Assert.notNull(listener, "AdvisedSupportListener must not be null");
		this.listeners.add(listener);
	}

	/**
	 * Remove the given AdvisedSupportListener from this proxy configuration.
	 * @param listener the listener to deregister
	 */
	public void removeListener(AdvisedSupportListener listener) {
		Assert.notNull(listener, "AdvisedSupportListener must not be null");
		this.listeners.remove(listener);
	}


	/**
	 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
	 * create an AOP proxy with {@code this} as an argument.
	 */
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

	/**
	 * Activate this proxy configuration.
	 * @see AdvisedSupportListener#activated
	 */
	private void activate() {
		this.active = true;
		for (AdvisedSupportListener listener : this.listeners) {
			listener.activated(this);
		}
	}

	/**
	 * Propagate advice change event to all AdvisedSupportListeners.
	 * @see AdvisedSupportListener#adviceChanged
	 */
	@Override
	protected void adviceChanged() {
		super.adviceChanged();
		synchronized (this) {
			if (this.active) {
				for (AdvisedSupportListener listener : this.listeners) {
					listener.adviceChanged(this);
				}
			}
		}
	}

	/**
	 * Subclasses can call this to check whether any AOP proxies have been created yet.
	 */
	protected final synchronized boolean isActive() {
		return this.active;
	}

}
ProxyCreatorSupport 这一层定义了private AopProxyFactory aopProxyFactory; 并提供了方便的配置方法。对子类暴露了
/**
 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
 * create an AOP proxy with {@code this} as an argument.
 */
protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	return getAopProxyFactory().createAopProxy(this);
}

主要就是调用AopProxyFactory.createAopProxy(AdvisedSupport config) 方法创建代理类,可见ProxyCreatorSupport 自己没有实现任何主要功能,只是提供了配置AopProxyFactory的方法,和调用AopProxyFactory的方法创建代理对象。这里调用AopProxyFactory.createAopProxy(AdvisedSupport config)的时候,传了 this ,这是把ProxyCreatorSupport当作一个AdvisedSupport对象来用了,因为ProxyCreatorSupport继承了AdvisedSupport,并且AdvisedSupport可以提供AopProxyFactory创建代理对象所需的所有配置信息

四、AopProxyFactory的默认实现类DefaultAopProxyFactory的介绍

/**
 * Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy
 * or a JDK dynamic proxy.
 *
 * <p>Creates a CGLIB proxy if one the following is true for a given
 * {@link AdvisedSupport} instance:
 * <ul>
 * <li>the {@code optimize} flag is set
 * <li>the {@code proxyTargetClass} flag is set
 * <li>no proxy interfaces have been specified
 * </ul>
 *
 * <p>In general, specify {@code proxyTargetClass} to enforce a CGLIB proxy,
 * or specify one or more interfaces to use a JDK dynamic proxy.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Sebastien Deleuze
 * @author Sam Brannen
 * @since 12.03.2004
 * @see AdvisedSupport#setOptimize
 * @see AdvisedSupport#setProxyTargetClass
 * @see AdvisedSupport#setInterfaces
 */
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	private static final long serialVersionUID = 7930414337282325166L;


	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!NativeDetector.inNativeImage() &&
				(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
				
			// proxyTargetClass == true 表示除了可以代理接口,还可以代理类,如果是targetClass是类,就通过cglib创建
			// 类的代理
			// hasNoUserSuppliedProxyInterfaces(config) == true 需要通过判断
			// targetClass 是接口或者类来决定 创建jdk动态代理,还是cglib动态代理
			
			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.");
			}
			// 如果代理的目标类是一个接口 或者 目标类本身也是一个代理类 或者 是Lambda表达式 创建jdk动态代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

	/**
	 * Determine whether the supplied {@link AdvisedSupport} has only the
	 * {@link org.springframework.aop.SpringProxy} interface specified
	 * (or no proxy interfaces specified at all).
	 */
	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}

五、Spring 中的 InvocationHandler --- JdkDynamicAopProxy

DefaultAopProxyFactory.createAopProxy(AdvisedSupport config)方法返回了一个AopProxy对象,AopProxy对象可能是一个JdkDynamicAopProxy对象也可能是一个ObjenesisCglibAopProxy对象
JdkDynamicAopProxy和CglibAopProxy都对AopProxy.getProxy()方法进行了实现,获取一个代理对象。
JdkDynamicAopProxy和CglibAopProxy都持有AdvisedSupport实例,所以他两都能获取到创建代理对象所需要的所有配置

这里重点说一下 JdkDynamicAopProxy,JdkDynamicAopProxy还继承了jdk动态代理中的InvocationHandler,并且在它自己实现的创建jdk动态代理的方法中,把自己作为InvocationHandler实例传了进去,所以当我们调用这个JdkDynamicAopProxy创建的代理对象的方法时,就会回调这个JdkDynamicAopProxy的invoke方法,在invoke方法中 需要用到的 targetSource , Advisor 和其他的配置都可以从它持有的AdvisedSupport实例中获取

六、AdvisedSupport .getInterceptorsAndDynamicInterceptionAdvice()

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	List<Object> cached = this.methodCache.get(cacheKey);
	if (cached == null) {
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
				this, method, targetClass);
		this.methodCache.put(cacheKey, cached);
	}
	return cached;
}

 可以看到调用advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                this, method, targetClass);的时候,传递了this ,this就是当前的AdvisedSupport对象,可以从这获取到Advisor,还传递了Method对象和目标对象的类型 targetClass。这样就可以通过用Advisor中的Pointcut对象,对 Method 和 targetClass 进行匹配,如果匹配成功了,那么这个Advisor中的Advice就得加入到本次调用的 MethodInterceptor 调用链中

七、AdvisorChainFactory 的默认实现类 DefaultAdvisorChainFactory

/**
 * A simple but definitive way of working out an advice chain for a Method,
 * given an {@link Advised} object. Always rebuilds each advice chain;
 * caching can be provided by subclasses.
 *
 * @author Juergen Hoeller
 * @author Rod Johnson
 * @author Adrian Colyer
 * @since 2.0.3
 */
@SuppressWarnings("serial")
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

	@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		//从AdvisedSupport实例中获取配置了的所有Advisor
		Advisor[] advisors = config.getAdvisors();
		//这里创建要返回的 MethodInterceptor 集合,注意这里设定了长度
		//这样可以节省内存,interceptorList最终的size最大也就是跟advisors.length差不多
		//就算所有的Advisor中的Pointcut都匹配成功,也就是把所有Advisor中的Advice
		//封装成 MethodInterceptor 添加到interceptorList中,不过在registry.getInterceptors(advisor)
		//中,一个Advice有可能被多个AdvisorAdapter支持,被封装到多个 MethodInterceptor
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		
		// 获取要代理的Class,用于 PointcutAdvisor 进行类型匹配
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		for (Advisor advisor : advisors) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				// config.isPreFiltered()确定代理配置是否已经预先过滤,仅包含适用于该代理目标类的顾问(advisors)
				// 如果预先过滤了,就不需要匹配代理目标类了,直接匹配方法
				// pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass) 用PointcutAdvisor中配置的
				// Pointcut 对代理目标类进行匹配
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
				
					// 获取Pointcut的方法匹配器
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					// 这是一种特殊的方法匹配器,匹配的时候还会考虑 introductions
					// 如果targetClass上没有introductions,方法的匹配效率会更高
					if (mm instanceof IntroductionAwareMethodMatcher) {
						if (hasIntroductions == null) {
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					else {
						// 非 IntroductionAwareMethodMatcher 匹配器匹配
						match = mm.matches(method, actualClass);
					}
					
					if (match) {
						// 如果方法也匹配成功,就需要这个 Advisor 中的Advice封装成 MethodInterceptor
						// 这里一个Advice有可能被多个AdvisorAdapter支持,被封装到多个 MethodInterceptor
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				// 如果时 IntroductionAdvisor 只匹配代理目标类就可以了
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

	/**
	 * Determine whether the Advisors contain matching introductions.
	 */
	private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
		for (Advisor advisor : advisors) {
			if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (ia.getClassFilter().matches(actualClass)) {
					return true;
				}
			}
		}
		return false;
	}

}

八、AdvisorAdapterRegistry 的 默认实现类 DefaultAdvisorAdapterRegistry

/**
 * Default implementation of the {@link AdvisorAdapterRegistry} interface.
 * Supports {@link org.aopalliance.intercept.MethodInterceptor},
 * {@link org.springframework.aop.MethodBeforeAdvice},
 * {@link org.springframework.aop.AfterReturningAdvice},
 * {@link org.springframework.aop.ThrowsAdvice}.
 *
 * @author Rod Johnson
 * @author Rob Harrop
 * @author Juergen Hoeller
 */
@SuppressWarnings("serial")
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


	/**
	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
	 */
	public DefaultAdvisorAdapterRegistry() {
		// 先注册三个 AdviceAdapter ,用于后面判断 advisor 中 Advice
		// 应该被封装为哪一种类型的 MethodInterceptor
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}


	@Override
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		Advice advice = (Advice) adviceObject;
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

	@Override
	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		List<MethodInterceptor> interceptors = new ArrayList<>(3);
		Advice advice = advisor.getAdvice();
		// 如果添加的 advice 本来就是MethodInterceptor 类型的
		// 直接添加到调用链中
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}
		// 遍历三个转换器,判断 advice 应该被封装为哪一种类型的 MethodInterceptor,
		// 封装完了之后,添加到调用链中
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[0]);
	}

	@Override
	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
		this.adapters.add(adapter);
	}

}


/**
 * Adapter to enable {@link org.springframework.aop.MethodBeforeAdvice}
 * to be used in the Spring AOP framework.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
@SuppressWarnings("serial")
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}

}


/**
 * Adapter to enable {@link org.springframework.aop.AfterReturningAdvice}
 * to be used in the Spring AOP framework.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
@SuppressWarnings("serial")
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof AfterReturningAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
		return new AfterReturningAdviceInterceptor(advice);
	}

}


/**
 * Adapter to enable {@link org.springframework.aop.ThrowsAdvice} to be used
 * in the Spring AOP framework.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
@SuppressWarnings("serial")
class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof ThrowsAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		return new ThrowsAdviceInterceptor(advisor.getAdvice());
	}

}

 我们看到Advice有可能被封装成,MethodBeforeAdviceInterceptor,AfterReturningAdviceInterceptor,ThrowsAdviceInterceptor ,也有可能本来就是MethodInterceptor类型的

public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
		implements AfterReturningAdvice, AfterAdvice, Serializable {
				
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements 
		MethodInterceptor, Serializable {
		
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice 
		implements MethodBeforeAdvice, Serializable {
		
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {

public class AspectJAfterAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {
通知类型实现的接口支持的AdviceAdapter被封装的MethodInterceptor
AspectJMethodBeforeAdviceMethodBeforeAdviceMethodBeforeAdviceAdapterMethodBeforeAdviceInterceptor
AspectJAfterReturningAdviceAfterReturningAdviceAfterReturningAdviceAdapterAfterReturningAdviceInterceptor
AspectJAfterAdviceMethodInterceptor直接使用MethodInterceptor本身
AspectJAfterThrowingAdviceMethodInterceptor直接使用MethodInterceptor本身
AspectJAroundAdviceMethodInterceptor直接使用MethodInterceptor本身

我们看到在基于AspectJ的这五种Advice中没有实现ThrowsAdvice的, ThrowsAdviceAdapter 和 ThrowsAdviceInterceptor 没有用到,其实我们可以自己来定义ThrowsAdvice实现

public class CustomThrowsAdvice implements ThrowsAdvice {

    public Object afterThrowing(ArithmeticException exeption){
        System.out.println("CustomThrowsAdvice.afterThrowing()");
        return exeption;
    }

    public Object afterThrowing(Method method , Object[] args , Object target , ArithmeticException exeption){
        System.out.println("CustomThrowsAdvice.afterThrowing()================");
        return exeption;
    }

}
/**
 * Interceptor to wrap an after-throwing advice.
 *
 * <p>The signatures on handler methods on the {@code ThrowsAdvice}
 * implementation method argument must be of the form:<br>
 *
 * {@code void afterThrowing([Method, args, target], ThrowableSubclass);}
 *
 * <p>Only the last argument is required.
 *
 * <p>Some examples of valid methods would be:
 *
 * <pre class="code">public void afterThrowing(Exception ex)</pre>
 * <pre class="code">public void afterThrowing(RemoteException)</pre>
 * <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, Exception ex)</pre>
 * <pre class="code">public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)</pre>
 *
 * <p>This is a framework class that need not be used directly by Spring users.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @see MethodBeforeAdviceInterceptor
 * @see AfterReturningAdviceInterceptor
 */
public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {

	private static final String AFTER_THROWING = "afterThrowing";

	private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class);


	private final Object throwsAdvice;

	/** Methods on throws advice, keyed by exception class. */
	private final Map<Class<?>, Method> exceptionHandlerMap = new HashMap<>();


	/**
	 * Create a new ThrowsAdviceInterceptor for the given ThrowsAdvice.
	 * @param throwsAdvice the advice object that defines the exception handler methods
	 * (usually a {@link org.springframework.aop.ThrowsAdvice} implementation)
	 */
	public ThrowsAdviceInterceptor(Object throwsAdvice) {
		Assert.notNull(throwsAdvice, "Advice must not be null");
		this.throwsAdvice = throwsAdvice;
		
		//创建 ThrowsAdviceInterceptor 的时候,先把传进来的ThrowsAdvice实例进行解析
		//获取实现类的所有方法进行遍历
		Method[] methods = throwsAdvice.getClass().getMethods();
		for (Method method : methods) {
			// 只有method.getName() == afterThrowing 并且 参数为1个或者四个的方法才可以
			if (method.getName().equals(AFTER_THROWING) &&
					(method.getParameterCount() == 1 || method.getParameterCount() == 4)) {
					
				// 获取方法的最后一个参数的具体类型
				Class<?> throwableParam = method.getParameterTypes()[method.getParameterCount() - 1];
				// 如果最后一个参数是 Throwable 的子类,就将这种Throwable的具体类型和这个afterThrowing方法做映射
				if (Throwable.class.isAssignableFrom(throwableParam)) {
					// An exception handler to register...
					this.exceptionHandlerMap.put(throwableParam, method);
					if (logger.isDebugEnabled()) {
						logger.debug("Found exception handler method on throws advice: " + method);
					}
				}
			}
		}

		// 如果一个方法名为afterThrowing
		// 如果定义的afterThrowing方法的参数个数不是1个或者4个
		// 如果定义的afterThrowing方法的最后一个参数不是Throwable的子类
		// 说明这个 ThrowsAdvice 的方法定义的不合格
		if (this.exceptionHandlerMap.isEmpty()) {
			throw new IllegalArgumentException(
					"At least one handler method must be found in class [" + throwsAdvice.getClass() + "]");
		}
	}


	/**
	 * Return the number of handler methods in this advice.
	 */
	public int getHandlerMethodCount() {
		return this.exceptionHandlerMap.size();
	}


	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		catch (Throwable ex) {
			// 如果在调用调用链后面的MethodInterceptor或者目标对象的方法是抛出了异常
			// 就用这个异常去找该异常有没有对应的 afterThrowing 方法
			// 如果有的话,回调该afterThrowing方法
			Method handlerMethod = getExceptionHandler(ex);
			if (handlerMethod != null) {
				invokeHandlerMethod(mi, ex, handlerMethod);
			}
			throw ex;
		}
	}

	/**
	 * Determine the exception handle method for the given exception.
	 * @param exception the exception thrown
	 * @return a handler for the given exception type, or {@code null} if none found
	 */
	@Nullable
	private Method getExceptionHandler(Throwable exception) {
		Class<?> exceptionClass = exception.getClass();
		if (logger.isTraceEnabled()) {
			logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
		}
		Method handler = this.exceptionHandlerMap.get(exceptionClass);
		while (handler == null && exceptionClass != Throwable.class) {
			exceptionClass = exceptionClass.getSuperclass();
			handler = this.exceptionHandlerMap.get(exceptionClass);
		}
		if (handler != null && logger.isTraceEnabled()) {
			logger.trace("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
		}
		return handler;
	}

	private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {
		Object[] handlerArgs;
		// 如果afterThrowing方法只有一个参数,只需要把异常作为参数就可以了
		if (method.getParameterCount() == 1) {
			handlerArgs = new Object[] {ex};
		}
		else {
			// 如果afterThrowing方法有四个参数,就得准备这四个参数
			handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};
		}
		try {
			// 调用ThrowsAdvice实例的afterThrowing方法
			method.invoke(this.throwsAdvice, handlerArgs);
		}
		catch (InvocationTargetException targetEx) {
			throw targetEx.getTargetException();
		}
	}

}

 按照 ThrowsAdviceInterceptor 的实现我们知道,自己定义ThrowsAdvice时必须满足几个条件
1.必须至少有一个方法的方法名为afterThrowing
2.afterThrowing方法的参数个数只能是1个或者4个
3.afterThrowing方法的最后一个参数只能是Throwable的子类

九、详细介绍 MethodInterceptor 

十、如何通过 MethodInterceptor 几个实现类实现 Advice 的顺序调用

十一、AdvisorChainFactory 的默认实现类 DefaultAdvisorChainFactory

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/923105.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++数据结构与算法

C数据结构与算法 1.顺序表代码模版 C顺序表模版 #include <iostream> using namespace std; // 可以根据需要灵活变更类型 #define EleType intstruct SeqList {EleType* elements;int size;int capacity; };// Init a SeqList void InitList(SeqList* list, int capa…

贵州茅台[600519]行情数据接口

贵州茅台&#xff1a;实时行情 Restful API # 测试接口&#xff1a;可以复制到浏览器打开 https://tsanghi.com/api/fin/stock/XSHG/realtime?tokendemo&ticker600519获取股票实时行情&#xff08;开、高、低、收、量&#xff09;。 请求方式&#xff1a;GET。 Python示例…

Node.js的http模块:创建HTTP服务器、客户端示例

新书速览|Vue.jsNode.js全栈开发实战-CSDN博客 《Vue.jsNode.js全栈开发实战&#xff08;第2版&#xff09;&#xff08;Web前端技术丛书&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 要使用http模块&#xff0c;只需要在文件中通过require(http)引入即可。…

互联网直播/点播EasyDSS视频推拉流平台视频点播有哪些技术特点?

在数字化时代&#xff0c;视频点播应用已经成为我们生活中不可或缺的一部分。监控技术与视频点播的结合正悄然改变着我们获取和享受媒体内容的方式。这一变革不仅体现在技术层面的进步&#xff0c;更深刻地影响了我们。 EasyDSS视频直播点播平台是一款高性能流媒体服务软件。E…

基于Boost库的搜索引擎

本专栏内容为&#xff1a;项目专栏 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;基于Boots的搜索引擎 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &#x1f339;&#x1f339;&#x1f339;关注我带你学习编程知识…

安全加固方案

交换机安全加固 查看是否关闭未使用的接口 25GE1/0/1、25GE1/0/47、25GE1/0/48需要使用&#xff0c;暂不关闭 system-view # interface Eth-Trunk99 shutdown quit interface Eth-Trunk100 shutdown quit interface Eth-Trunk110 shutdown quit interface 25GE1/…

Wonder3D本地部署到算家云搭建详细教程

Wonder3D简介 Wonder3D仅需2至3分钟即可从单视图图像中重建出高度详细的纹理网格。Wonder3D首先通过跨域扩散模型生成一致的多视图法线图与相应的彩色图像&#xff0c;然后利用一种新颖的法线融合方法实现快速且高质量的重建。 本文详细介绍了在算家云搭建Wonder3D的流程以及…

TMS FNC UI Pack 5.4.0 for Delphi 12

TMS FNC UI Pack是适用于 Delphi 和 C Builder 的多功能 UI 控件的综合集合&#xff0c;提供跨 VCL、FMX、LCL 和 TMS WEB Core 等平台的强大功能。这个统一的组件集包括基本工具&#xff0c;如网格、规划器、树视图、功能区和丰富的编辑器&#xff0c;确保兼容性和简化的开发。…

C# 命令行运行包

环境&#xff1a;net6 nuget包&#xff1a;Cliwrap 3.6.7 program&#xff1a; 相当于cmd运行命令&#xff1a;nuget search json static async Task Main(string[] args) {var cmd Cli.Wrap("D:\\软件\\Nuget\\nuget.exe").WithArguments(args >args.Add("…

Python 之网络爬虫

一.认识HTML 1.什么是HTML &#xff08;HyperText Markup Language&#xff09; HTML是超文本标记语言的缩写&#xff0c;它包含一系列的标签&#xff0c; “超文本”是一种组织信息的方式&#xff0c;利用HTML标记&#xff0c;告诉浏览器被标记的内容如何显示到浏览器页面上…

【数据分享】2001-2023年我国30米分辨率冬小麦种植分布栅格数据(免费获取)

小麦、玉米、水稻等各类农作物的种植分布数据在农业、环境、国土等很多专业都经常用到&#xff01; 本次给大家分享的是我国2001-2023年逐年的30米分辨率冬小麦种植分布栅格数据&#xff01;数据格式为TIFF格式&#xff0c;数据坐标为GCS_WGS_1984。该数据包括我国11个省份的冬…

C语言菜鸟入门·关键字·union的用法

目录 1. 简介 2. 访问成员 2.1 声明 2.2 赋值 3. 共用体的大小 4. 与typedef联合使用 5. 更多关键字 1. 简介 共用体&#xff08;union&#xff09;是一种数据结构&#xff0c;它允许在同一内存位置存储不同的数据类型&#xff0c;但每次只能存储其中一种类型的…

嵌入式驱动开发详解3(pinctrl和gpio子系统)

文章目录 前言pinctrl子系统pin引脚配置pinctrl驱动详解 gpio子系统gpio属性配置gpio子系统驱动gpio子系统API函数与gpio子系统相关的of函数 pinctrl和gpio子系统的使用设备树配置驱动层部分用户层部分 前言 如果不用pinctrl和gpio子系统的话&#xff0c;我们开发驱动时需要先…

低代码搭建crm系统实现财务管理功能模块

实例背景&#xff1a; CRM的项目&#xff0c;客户想要实现一个简单的财务记账功能&#xff0c;记录订单应收账款及收款记录。 具体要求&#xff1a; 1、要求收款时可以实时计算本次收款后的剩余应收。 2、要求记录AR的收款状态&#xff1a;未收款、部分收款、已收款。 实现…

C51相关实验

C51相关实验 LED //功能&#xff1a;1.让开发板的LED全亮&#xff0c;2,点亮某一个LED,3.让LED3以5Hz的频率闪动#include "reg52.h"#define LED P2 sbit led1 LED^1;void main(void) {LED 0xff;//LED全灭led1 0;while(1)//保持应用程序不退出{} }LED 输出端是高…

【测试工具JMeter篇】JMeter性能测试入门级教程(一)出炉,测试君请各位收藏了!!!

一、前言 Apache JMeter是纯Java的开源软件&#xff0c;最初由Apache软件基金会的Stefano Mazzocchi开发&#xff0c;旨在加载测试功能行为和测量性能。可以使用JMeter进行性能测试&#xff0c;即针对重负载、多用户和并发流量测试Web应用程序。 我们选择JMeter原因 是否测试过…

人工智能(AI)与机器学习(ML)基础知识

目录 1. 人工智能与机器学习的核心概念 什么是人工智能&#xff08;AI&#xff09;&#xff1f; 什么是机器学习&#xff08;ML&#xff09;&#xff1f; 什么是深度学习&#xff08;DL&#xff09;&#xff1f; 2. 机器学习的三大类型 &#xff08;1&#xff09;监督式学…

STM32WB55RG开发(5)----监测STM32WB连接状态

STM32WB55RG开发----5.生成 BLE 程序连接手机APP 概述硬件准备视频教学样品申请源码下载参考程序选择芯片型号配置时钟源配置时钟树RTC时钟配置RF wakeup时钟配置查看开启STM32_WPAN条件配置HSEM配置IPCC配置RTC启动RF开启蓝牙LED配置设置工程信息工程文件设置参考文档SVCCTL_A…

虚拟机CentOS系统通过Docker部署RSSHub并映射到主机

公告 &#x1f4cc;更新公告 20241124-该文章已同步更新到作者的个人博客&#xff08;链接&#xff1a;虚拟机CentOS系统通过Docker部署RSSHub并映射到主机&#xff09; 一、编辑 YUM 配置文件 1、打开 CentOS 系统中的 YUM 软件仓库配置文件 vim /etc/yum.repos.d/CentOS-Ba…

React(五)——useContecxt/Reducer/useCallback/useRef/React.memo/useMemo

文章目录 项目地址十六、useContecxt十七、useReducer十八、React.memo以及产生的问题18.1组件嵌套的渲染规律18.2 React.memo18.3 引出问题 十九、useCallback和useMemo19.1 useCallback对函数进行缓存19.2 useMemo19.2.1 基本的使用19.2.2 缓存属性数据 19.2.3 对于更新的理解…