Spring AOP代理用的到底是CGLIB还是JDK动态代理

先放结论:

  1. 默认使用 JDK 动态代理,这样便可以代理所有的接口类型(interface)
  2. Spring AOP也支持CGLIB的代理方式。如果我们被代理对象没有实现任何接口,或者接口没有方法,则默认是CGLIB
  3. 我们可以强制使用CGLIB,指定proxy-target-class = “true” 或者 基于注解@EnableAspectJAutoProxy(proxyTargetClass = true)

Spring源码中,在选择代理的方式之前,对proxyTargetClass属性有这样一步处理:

org.springframework.aop.framework.ProxyProcessorSupport

	/**
	 * Check the interfaces on the given bean class and apply them to the {@link ProxyFactory},
	 * if appropriate.
	 * <p>Calls {@link #isConfigurationCallbackInterface} and {@link #isInternalLanguageInterface}
	 * to filter for reasonable proxy interfaces, falling back to a target-class proxy otherwise.
	 * @param beanClass the class of the bean
	 * @param proxyFactory the ProxyFactory for the bean
	 */
	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) {
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;
				break;
			}
		}
		if (hasReasonableProxyInterface) {
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		else {
			proxyFactory.setProxyTargetClass(true);
		}
	}

看第12-18行,如果bean所实现的所有接口都为空接口(没有需要实现的方法),那么最后会走else分支,调用setProxyTargetClass(true),其实也就是设置了proxyTargetClass为true。

即默认使用JDK动态代理,如果没有实现接口,或者接口没有方法,这里会自动设置proxyTargetClass为true,即切换为使用CGLIB代理

选择代理方式时候,会根据config.isProxyTargetClass()来决定使用哪个代理:

org.springframework.aop.framework.DefaultAopProxyFactory

@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		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);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

config.isProxyTargetClass() 为true,会进入第一个if分支里面。在这个分支里面,如果bean它本身是一个interface或者是本身已经是一个代理对象,那么就会创建JDK代理,否则会使用CGLIB的方式创建代理对象。

参考:https://blog.csdn.net/w449226544/article/details/103365446

© 版权声明
THE END
喜欢就支持一下吧
点赞6赞赏 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容