先放结论:
- 默认使用 JDK 动态代理,这样便可以代理所有的接口类型(interface)
- Spring AOP也支持CGLIB的代理方式。如果我们被代理对象没有实现任何接口,或者接口没有方法,则默认是CGLIB
- 我们可以强制使用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
请登录后查看评论内容