4.springboot代理实现

发布于:2025-02-11 ⋅ 阅读:(98) ⋅ 点赞:(0)

1.概述

上篇本文介绍spring动态代理创建器自动创建动态代理的过程。本文介绍spring代理的实现方式(jdk动态代理 & cglib动态代理);

2.动态代理简介

我们先熟悉下两种动态代理的实现方式;

A.jdk动态代理

  • 定义一个接口Car(jdk动态代理类必须实现至少一个接口);
  • 定义一个实现类Suv(被代理的目标类);
  • 定义一个InvocationHandler实现类CarProxy(持有Suv对象的引用,实现接口中的invoke方法);
  • 使用Proxy.newProxyInstance创建代理对象carProxy;
  • 使用代理对象调用目标类的方法: carProxy.drive(“张三”);
/**
 * 测试jdk动态代理
 * 1.定义一个接口Car(jdk动态代理类必须实现至少一个接口)
 * 2.定义一个实现类Suv(被代理的目标类)
 * 3.定义一个InvocationHandler实现类CarProxy(持有Suv对象的引用,实现接口中的invoke方法)
 * 4.使用Proxy.newProxyInstance创建代理对象carProxy
 * 5.使用代理对象调用目标类的方法: carProxy.drive("张三")
 */
public interface Car {

    void drive(String name);

    /**
     * 实现类
     */
    @Slf4j
    class Suv implements Car {

        @Override
        public void drive(String name) {
            log.info("司机:{}开车", name);
        }
    }

    /**
     * 代理逻辑
     */
    @Slf4j
    class CarProxy implements InvocationHandler {

        private final Car car;

        public CarProxy(Car car) {
            this.car = car;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            log.info("代理,目标方法运行之前");
            Object rst = method.invoke(car, args);
            log.info("代理,目标方法运行之后");

            return rst;
        }
    }

    static void main(String[] args) {
        Car car = new Suv();
        Class<?> cla = car.getClass();

        //**创建动态代理
        Car carProxy = (Car)Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), new CarProxy(car));
        carProxy.drive("张三");
        carProxy.toString();
    }
}

B.cglib动态代理

  • 定义一个类Suv(不用实现接口,当然也可以实现接口);
  • 定义一个MethodInterceptor(Callback的子接口)实现类CarProxy;
  • 使用Enhancer.create创建代理对象carProxy;
  • 使用代理对象调用目标类的方法: carProxy.drive(“张三”);
/**
 * 测试cglib动态代理
 * 1.定义一个类Suv(不用实现接口,当然也可以实现接口)
 * 2.定义一个MethodInterceptor(Callback的子接口)实现类CarProxy
 * 3.使用Enhancer.create创建代理对象carProxy
 * 4.使用代理对象调用目标类的方法: carProxy.drive("张三")
 */
@Slf4j
public class Suv {

    public void drive(String name) {
        log.info("司机:{}开车", name);
    }

    @Override
    public String toString() {
        log.info("suv toString");
        return "suv";
    }

    /**
     * 代理逻辑
     * MethodInterceptor为Callback的子接口
     */
    @Slf4j
    static class CarProxy implements MethodInterceptor {

        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            log.info("代理,目标方法运行之前");
            Object rst = proxy.invokeSuper(obj, args);
            log.info("代理,目标方法运行之后");

            return rst;
        }
    }

    public static void main(String[] args) {
        //**创建动态代理
        Suv carProxy = (Suv) Enhancer.create(Suv.class, new CarProxy());
        carProxy.drive("张三");
        carProxy.toString();
    }
}

  • cglib动态代理每一个代理逻辑就是一个Callback。创建代理类时,可同时定义多个Callback,然后通过CallbackFilter查找指定方法需执行的Callback;
/**
 * 过滤器
 * 使用CallbackHelper快速实现CallbackFilter
 */
public class CarFilter extends CallbackHelper {

    public CarFilter(Class superclass, Class[] interfaces) {
        super(superclass, interfaces);
    }

    @Override
    protected Object getCallback(Method method) {
        //**只代理drive方法
        return "drive".equals(method.getName()) ? new CarProxy() : NoOp.INSTANCE;
    }
}

public static void main(String[] args) {
    //**创建动态代理,使用过滤器
    CarFilter filter = new CarFilter(Suv.class, null);
    Suv carProxy1 = (Suv) Enhancer.create(Suv.class, null, filter, filter.getCallbacks());
    carProxy1.drive("李四");
    carProxy1.toString();
}

3.动态代理实现

在上一步我们了解的动态代理的基本概念和实现方式,这里我们看一下spring如何使用jdk动态代理 & cglib动态代理创建动态代理类;

概念

  • 是否静态的(TargetSource.isStatic()):
    TargetSource是对原始bean的封装。每次调用TargetSource.getTarget()返回的原始bean都是同一个对象,则为true。一般是指原始bean为单例;
  • 是否暴露代理(AdvisedSupport.isExposeProxy()):
    如果允许暴露代理,在执行目标方法的过程中会把代理对象设置到ThreadLocal中,可从该ThreadLocal获取当前执行的代理对象;
  • 是否冻结(AdvisedSupport.isFrozen()):
    如果是冻结的,表示针对原始bean的拦截器链是固定不变的。即配置的aop代理是固定的,没有动态配置;

核心类图

«Interface»
InvocationHandler
//**jdk动态代理接口
+//**jdk动态代理方法()
+Object invoke(Object proxy, Method method, Object[] args)
«Interface»
AopProxy
//**Aop代理接口
+//**获取代理对象()
+Object getProxy()
+//**获取代理对象()
+Object getProxy(ClassLoader classLoader)
+//**获取代理class对象()
+Class getProxyClass(ClassLoader classLoader)
JdkDynamicAopProxy
//**jdk动态代理实现
//**AdvisedSupport,代理相关的配置
- AdvisedSupport advised;
//**代理的接口
- Class[] proxiedInterfaces;
//**代理的接口是否定义了equals方法
- boolean equalsDefined;
//**代理的接口是否定义了hashCode方法
- boolean hashCodeDefined;
-//**在代理类的接口查找equals和hashCode方法()
-void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces)
+//**重写equals方法()
+boolean equals(@Nullable Object other)
+//**重写hashCode方法()
+int hashCode()
CglibAopProxy
//**Cglib代理实现
//**验证原始bean的方法是否支持cglib代理,并打印日志
- Map, Boolean> validatedClasses;
//**AdvisedSupport,代理相关的配置
# AdvisedSupport advised;
//**原始bean的构造方法参数
# Object[] constructorArgs;
//**原始bean构造方法参数的类型
# Class[] constructorArgTypes;
//**Callback的子类,把代理bean方法的调用转发给AdvisedSupport
- AdvisedDispatcher advisedDispatcher;
- Map fixedInterceptorMap;
- int fixedInterceptorOffset;
-//**创建代理bean的核心逻辑()
-buildProxy(ClassLoader classLoader, boolean classOnly)
-//**验证原始bean的方法是否支持cglib代理()
-validateClassIfNecessary(Class proxySuperClass, ClassLoader classLoader)
-//**获取代理逻辑Callback()
-Callback[] getCallbacks(Class rootClass)
#//**创建代理bean的class对象()
#Class createProxyClass(Enhancer enhancer)
#//**创建代理bean()
#Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)
#//**创建代理Enhancer()
#Enhancer createEnhancer()
ObjenesisCglibAopProxy
//**基于Objenesis的Cglib代理实现
//**Objenesis创建实例时不需构造函数
#//**创建代理bean的class对象()
#Class createProxyClass(Enhancer enhancer)
#//**创建代理bean()
#Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)

核心类说明

A.AopProxy

创建动态代理接口,提供3个方法,创建创建代理bean和代理bean的class对象;

B.JdkDynamicAopProxy

  • AopProxy的jdk动态代理实现,使用jdk动态代理创建代理bean和class;
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	...
	//**使用jdk动态代理创建代理bean
	return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

@Override
public Class<?> getProxyClass(@Nullable ClassLoader classLoader) {
    //**使用jdk动态代理创建代理bean的class对象
	return Proxy.getProxyClass(classLoader, this.proxiedInterfaces);
}
  • JdkDynamicAopProxy同时继承InvocationHandler,实现了invoke方法;
    • 调用equals和hashCode方法
      如果原始bean的接口定义了equals和hashCode方法,则直接调用原始bean的实现,否则调用JdkDynamicAopProxy的实现;
    • 调用Advised接口方法
      转为调用Advised实例的方法。一般场景调用不到Advised接口的方法,可能使用反射可以调用;
    • 调用其它方法(原始bean的接口定义的方法)
      先查找目标方法的代理配置。如果存在代理配置就调用代理逻辑,然后调用原始bean的目标方法。如果不存在就直接调用原始bean的目标方法;
@Override
@Nullable //**如果可能会返回null,加上这个标识,提示调用者
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 {//**如果接口没有定义equals和hashCode方法,则调用此类的equals和hashCode方法
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			return hashCode();
		}
		//**没发现实际用处
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		//**调用Advised接口的方法
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;
		
		//**把代理对象设置到ThreadLocal中
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		//**获取原始bean和class对象
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		//**查找调用方法的拦截
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		if (chain.isEmpty()) {//**如果Interceptor列表为空,直接调用目标方法
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {//**调用Interceptor链(依次调用每个Interceptor)
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			retVal = invocation.proceed();
		}

		//**处理返回值类型
		
		return retVal;
	}
	finally {
		//**释放资源
	}
}

C.CglibAopProxy

AopProxy的cglib动态代理实现,使用cglib动态代理创建代理bean和class。创建代理bean的核心代码;

  • 创建Enhancer(用于创建cglib动态代理bean);
  • 获取Callback(把代理逻辑封装成Callback);
  • 设置CallbackFilter(CallbackFilter可以查找指定方法需执行的Callback);
  • 创建代理bean/class;
//**创建代理bean和class的核心逻辑
private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly) {
	try {//**获取&验证原始bean的class对象
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
		
		//**如果原始bean仍然是cglib代理bean,获取上一级的原始bean和接口
		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);
			}
		}

		//**验证原始bean的方法是否支持cglib代理,不符合也只是打印日志而已
		validateClassIfNecessary(proxySuperClass, classLoader);

		//**创建Enhancer(用于创建cglib动态代理bean)
		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader smartClassLoader &&
					smartClassLoader.isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setAttemptLoad(true);
		enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
		
		//**获取Callback(把代理逻辑封装成Callback)
		Callback[] callbacks = getCallbacks(rootClass);
		//**获取Callback的class对象
		Class<?>[] types = new Class<?>[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		
		//**设置CallbackFilter(CallbackFilter可以查找指定方法需执行的Callback)
		//**ProxyCallbackFilter是一个CallbackFilter的实现,内部类&私有,外部无法访问
		enhancer.setCallbackFilter(new ProxyCallbackFilter(
				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);

		//**创建代理bean/class
		return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks));
	}
	//**异常处理
}

根据原始bean的class对象获取Callback列表;

  • 创建创建Callback数组。调用代理bean的目标方法时,会根据CallbackFilter过滤。根据使用场景分类如下:
    • 支持目标方法有一个/多个代理配置
      调用时会按顺序调用拦截器链,最后调用原始bean的目标方法;
      • DynamicAdvisedInterceptor,默认的Callback。支持TargetSource和拦截器链是动态的,调用目标方法时才会获取TargetSource和拦截器链;
      • FixedChainStaticTargetInterceptor,静态的Callback。TargetSource和拦截器链必须是固定不变的,创建时就会初始化,调用时直接使用初始化的TargetSource和拦截器链;
    • 目标方法没有任何代理配置
      原始bean的任何方法配置了代理,就会创建代理bean,但是有些方法是没有配置代理的,不需要调用其它代理逻辑;
      • StaticUnadvisedExposedInterceptor & StaticUnadvisedInterceptor适用于静态TargetSource & 无代理配置。前者会暴露代理;
      • DynamicUnadvisedExposedInterceptor & DynamicAdvisedInterceptor适用于动态TargetSource & 无代理配置。前者会暴露代理;
    • 目标调度程序,会把调用转发给其它对象
      StaticDispatcher & AdvisedDispatcher,前者转发给原始bean,后者转发给AdvisedSupport;
    • Spring针对固定方法生成默认的代理逻辑
      EqualsInterceptor & HashCodeInterceptor,支持equals和HashCode方法调用的Callback;
  • 针对静态的(原始bean为单例) & 冻结的(Advice链是固定的),则进行一些优化。避免调用目标方法时动态去过滤需要执行的Callback;
    • 为每个目标方法创建一个固定的Callback(FixedChainStaticTargetInterceptor)。即每个方法都有一个Callback;
    • 把所有的FixedChainStaticTargetInterceptor添加到Callback数组的末尾;
    • 记录每个方法对应FixedChainStaticTargetInterceptor在Callback数组的索引;
    • 进行上述优化的好处: 调用目标方法时可以直接根据索引找到Callback,避免进行额外的查找;
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
	//**代理配置: 是否暴露代理
	boolean exposeProxy = this.advised.isExposeProxy();
	//**代理配置: 是否冻结
	boolean isFrozen = this.advised.isFrozen();
	//**否是静态的(每次调用getTarget()返回的原始bean都是同一个对象,一般是指原始bean为单例)
	boolean isStatic = this.advised.getTargetSource().isStatic();
	
	//**开始创建Callback数组,每个Callback元素处理一种类型。调用代理bean的目标方法时,会根据CallbackFilter查找Callback

	/**
	 * 1.DynamicAdvisedInterceptor,适用于执行设置了aop拦截的目标方法
	 *   DynamicAdvisedInterceptor会按顺序调用拦截器链,最后调用原始bean的目标方法
	 **/
	Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
	
	/**
	 * 以下的4个Callback都是适用于直接执行原始bean的目标方法,没有代理逻辑。
	 * 前两个和后两个的区别:后两个次调用时需要先调用this.targetSource.getTarget()获取原始bean
	 * 2.StaticUnadvisedExposedInterceptor,StaticUnadvisedInterceptor
	 *   适用于静态TargetSource的Callback,区别就是是否暴露代理
	 * 3.DynamicUnadvisedExposedInterceptor,DynamicAdvisedInterceptor
	 *   适用于非静态TargetSource的Callback,区别就是是否暴露代理
	 **/
	Callback targetInterceptor;
	if (exposeProxy) { //**如果允许暴露代理,在执行目标方法的过程中会把代理对象设置到ThreadLocal中
		targetInterceptor = (isStatic ?
				new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
				new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
	}
	else {
		targetInterceptor = (isStatic ?
				new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
				new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
	}

	//**静态目标调度程序,直接转发给原始bean
	Callback targetDispatcher = (isStatic ?
			new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
			
	//**主要的Callback数组
	Callback[] mainCallbacks = new Callback[] {
			aopInterceptor,  //**默认的Callback
			targetInterceptor,  //**直接调用原始bean的Callback
			new SerializableNoOp(),  //**空Callback。Callback不支持空值,以此代替空值
			targetDispatcher, this.advisedDispatcher, //**目标调度程序,前者转发给原始bean,后者转发给AdvisedSupport
			new EqualsInterceptor(this.advised), //**支持equals方法的Callback
			new HashCodeInterceptor(this.advised) //**支持hashCode方法的Callback
	};

	Callback[] callbacks;

	/**
	 * 如果是静态的(原始bean为单例) & 是冻结的(Advice链是固定的),则进行优化
	 * 1.查找每个方法的拦截器链,并封装为FixedChainStaticTargetInterceptor。即每个方法都有一个FixedChainStaticTargetInterceptor
	 * 2.把所有的FixedChainStaticTargetInterceptor添加到Callback数组的末尾
	 * 3.记录每个方法对应FixedChainStaticTargetInterceptor在Callback数组的索引
	 * 进行上述优化的好处: 调用目标方法时可以直接根据索引找到Callback,避免进行额外的查找
	 **/
	if (isStatic && isFrozen) {
		Method[] methods = rootClass.getMethods();
		Callback[] fixedCallbacks = new Callback[methods.length];
		this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);

		for (int x = 0; x < methods.length; x++) {
			Method method = methods[x];
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
			fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
					chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
			this.fixedInterceptorMap.put(method, x);
		}

		callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
		System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
		System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
		this.fixedInterceptorOffset = mainCallbacks.length;
	}
	else {
		callbacks = mainCallbacks;
	}
	return callbacks;
}

创建代理bean/class的逻辑,创建实例使用到原始bean的构造器和参数;

//**创建代理bean的class对象
protected Class<?> createProxyClass(Enhancer enhancer) {
	enhancer.setInterceptDuringConstruction(false);
	return enhancer.createClass();
}

//**创建代理bean
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
	enhancer.setInterceptDuringConstruction(false);
	//**设置Callback(代理逻辑)
	enhancer.setCallbacks(callbacks);
	//**使用构造器和参数创建代理bean
	return (this.constructorArgs != null && this.constructorArgTypes != null ?
			enhancer.create(this.constructorArgTypes, this.constructorArgs) :
			enhancer.create());
}

网站公告

今日签到

点亮在社区的每一天
去签到