得到 AopProxy 实例化对象(CglibAopProxy 或 JdkDynamicAopProxy)后,开始创建目标对象的代理对象。
使用JDK动态代理还是CGLIB?
到这里对于到底使用哪种方式的代理可以做一个小总结:
- 如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理实现 AOP。
- 如果目标对象实现了接口,可以强制使用 CGLIB 实现 AOP。
- 如果目标对象没有实现接口,必须采用 CGLIB 库,Spring 会自动在 JDK 动态代理和 CGLIB 之间转换。
强制使用CGLIB代理的方式 <aop:aspectj-autoproxy proxy-target-class="true"/>
JDK 动态代理和 CGLIB 字节码生成的区别?
- JDK 动态代理只能对实现了接口的类生成代理,而不能针对类;
CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成 final。
CglibAopProxy
获🉐代理对象从 getProxy 方法开始 (接口 AopProxy 定义)
首先做的事情就是配置 Enhancer 对象,如下所示:@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {// logif (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}// 配置 Enhancer 对象try {// 获取需要代理的对象的Class对象Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;// 判断Class是否为cglib生成的Class(会有$$前缀)if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {// 如果是的话,获取其代理的对象的接口们proxySuperClass = rootClass.getSuperclass();Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.// 验证类的方法是否能代理,不能的话打印下日志validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...Enhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);// 判断是否使用缓存if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}// 设置代理对象enhancer.setSuperclass(proxySuperClass);// 设置代理对象的接口enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));// 代理对象命名规则enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);// 设置类加载器enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));// 一些回调方法,其中包括我们自定义的增强方法Callback[] callbacks = getCallbacks(rootClass);// 回调接口的Class对象Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.return createProxyClassAndInstance(enhancer, callbacks);} catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class", ex);} catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}
然后进入方法 createProxyClassAndInstance 创建代理对象。该方法由子类重写完成。
org.springframework.aop.framework.ObjenesisCglibAopProxy#createProxyClassAndInstance
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {// 代理对象的Class对象Class<?> proxyClass = enhancer.createClass();// 代理对象实例Object proxyInstance = null;// 尝试使用SpringObjenesis创建对象,不行的话再使用构造方法创建对象if (objenesis.isWorthTrying()) {try {proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());} catch (Throwable ex) {logger.debug("Unable to instantiate proxy using Objenesis, " +"falling back to regular proxy construction", ex);}}if (proxyInstance == null) {// Regular instantiation via default constructor...try {Constructor<?> ctor = (this.constructorArgs != null ?proxyClass.getDeclaredConstructor(this.constructorArgTypes) :proxyClass.getDeclaredConstructor());ReflectionUtils.makeAccessible(ctor);proxyInstance = (this.constructorArgs != null ? ctor.newInstance(this.constructorArgs) : ctor.newInstance());} catch (Throwable ex) {throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +"and regular proxy instantiation via default constructor fails as well", ex);}}((Factory) proxyInstance).setCallbacks(callbacks);return proxyInstance;}
JdkDynamicAopProxy
也是从 getProxy 方法开始。
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {// logif (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());}// 获得代理对象所有的接口Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);// 判断接口是否定义了equals和hashcode方法findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);// jdk动态代理创建代理对象return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}
JdkDynamicAopProxy 本身就实现了 InvocationHandler 方法,其invoke方法如下:
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);}}}
