From f558396e91bd3eb5c88ce803569f11c31233c1c8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 6 Feb 2014 20:25:11 +0100 Subject: [PATCH] Introduced SpringNamingPolicy for CGLIB Issue: SPR-11398 (cherry picked from commit 8c4e372) --- .../aop/framework/CglibAopProxy.java | 31 +++++++-------- ...CglibSubclassingInstantiationStrategy.java | 13 +++---- .../support/SimpleInstantiationStrategy.java | 6 +-- .../ConfigurationClassEnhancer.java | 12 +++--- .../cglib/core/SpringNamingPolicy.java | 39 +++++++++++++++++++ ...MemorySafeUndeclaredThrowableStrategy.java | 15 ++++--- 6 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 spring-core/src/main/java/org/springframework/cglib/core/SpringNamingPolicy.java diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java index 34f4e102f55..e08640904fc 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ import org.springframework.aop.RawTargetAccess; import org.springframework.aop.TargetSource; import org.springframework.aop.support.AopUtils; import org.springframework.cglib.core.CodeGenerationException; +import org.springframework.cglib.core.SpringNamingPolicy; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.CallbackFilter; import org.springframework.cglib.proxy.Dispatcher; @@ -181,20 +182,20 @@ final class CglibAopProxy implements AopProxy, Serializable { } } enhancer.setSuperclass(proxySuperClass); - enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class)); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); + enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); + enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class)); enhancer.setInterceptDuringConstruction(false); Callback[] callbacks = getCallbacks(rootClass); - enhancer.setCallbacks(callbacks); - enhancer.setCallbackFilter(new ProxyCallbackFilter( - this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); - - Class[] types = new Class[callbacks.length]; + Class[] types = new Class[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } + enhancer.setCallbackFilter(new ProxyCallbackFilter( + this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); + enhancer.setCallbacks(callbacks); // Generate the proxy class and create a proxy instance. Object proxy; @@ -312,8 +313,7 @@ final class CglibAopProxy implements AopProxy, Serializable { Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap(methods.length); - // TODO: small memory optimisation here (can skip creation for - // methods with no advice) + // TODO: small memory optimisation here (can skip creation for methods with no advice) for (int x = 0; x < methods.length; x++) { List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( @@ -340,16 +340,15 @@ final class CglibAopProxy implements AopProxy, Serializable { */ private static Object processReturnType(Object proxy, Object target, Method method, Object retVal) { // Massage return value if necessary - if (retVal != null && retVal == target && - !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { - // Special case: it returned "this". - // Note that we can't help if the target sets a reference - // to itself in another returned object. + if (retVal != null && retVal == target && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { + // Special case: it returned "this". Note that we can't help + // if the target sets a reference to itself in another returned object. retVal = proxy; } Class returnType = method.getReturnType(); if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { - throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method); + throw new AopInvocationException( + "Null return value from advice does not match primitive return type for: " + method); } return retVal; } @@ -851,7 +850,7 @@ final class CglibAopProxy implements AopProxy, Serializable { @Override public boolean equals(Object other) { - if (other == this) { + if (this == other) { return true; } if (!(other instanceof ProxyCallbackFilter)) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java index dc601c3bd4b..fef8fde389f 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; - +import org.springframework.cglib.core.SpringNamingPolicy; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.CallbackFilter; import org.springframework.cglib.proxy.Enhancer; @@ -72,7 +72,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt @Override protected Object instantiateWithMethodInjection( RootBeanDefinition beanDefinition, String beanName, BeanFactory owner, - Constructor ctor, Object[] args) { + Constructor ctor, Object[] args) { return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args); } @@ -104,9 +104,10 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt * Ignored if the ctor parameter is {@code null}. * @return new instance of the dynamically generated class */ - public Object instantiate(Constructor ctor, Object[] args) { + public Object instantiate(Constructor ctor, Object[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.beanDefinition.getBeanClass()); + enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setCallbackFilter(new CallbackFilterImpl()); enhancer.setCallbacks(new Callback[] { NoOp.INSTANCE, @@ -114,9 +115,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt new ReplaceOverrideMethodInterceptor() }); - return (ctor == null) ? - enhancer.create() : - enhancer.create(ctor.getParameterTypes(), args); + return (ctor != null ? enhancer.create(ctor.getParameterTypes(), args) : enhancer.create()); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java index b06904221f1..cdc12a1dbfc 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java @@ -62,14 +62,14 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { synchronized (beanDefinition.constructorArgumentLock) { constructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { - final Class clazz = beanDefinition.getBeanClass(); + final Class clazz = beanDefinition.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Constructor run() throws Exception { + public Constructor run() throws Exception { return clazz.getDeclaredConstructor((Class[]) null); } }); @@ -132,7 +132,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { * Instantiation should use the given constructor and parameters. */ protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition, - String beanName, BeanFactory owner, Constructor ctor, Object[] args) { + String beanName, BeanFactory owner, Constructor ctor, Object[] args) { throw new UnsupportedOperationException( "Method Injection not supported in SimpleInstantiationStrategy"); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java index 0f1b97f4824..d83aafbebd6 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.support.SimpleInstantiationStrategy; +import org.springframework.cglib.core.SpringNamingPolicy; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.CallbackFilter; import org.springframework.cglib.proxy.Enhancer; @@ -103,8 +104,9 @@ class ConfigurationClassEnhancer { private Enhancer newEnhancer(Class superclass) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(superclass); - enhancer.setInterfaces(new Class[] {EnhancedConfiguration.class}); + enhancer.setInterfaces(new Class[]{EnhancedConfiguration.class}); enhancer.setUseFactory(false); + enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setCallbackFilter(CALLBACK_FILTER); enhancer.setCallbackTypes(CALLBACK_TYPES); return enhancer; @@ -128,9 +130,9 @@ class ConfigurationClassEnhancer { * Facilitates idempotent behavior for {@link ConfigurationClassEnhancer#enhance(Class)} * through checking to see if candidate classes are already assignable to it, e.g. * have already been enhanced. - *

Also extends {@link DisposableBean}, as all enhanced - * {@code @Configuration} classes must de-register static CGLIB callbacks on - * destruction, which is handled by the (private) {@code DisposableBeanMethodInterceptor}. + *

Also extends {@link DisposableBean}, as all enhanced {@code @Configuration} + * classes must de-register static CGLIB callbacks on destruction, which is handled + * by the (private) {@code DisposableBeanMethodInterceptor}. *

Note that this interface is intended for framework-internal use only, however * must remain public in order to allow access to subclasses generated from other * packages (i.e. user code). diff --git a/spring-core/src/main/java/org/springframework/cglib/core/SpringNamingPolicy.java b/spring-core/src/main/java/org/springframework/cglib/core/SpringNamingPolicy.java new file mode 100644 index 00000000000..839f36f8b37 --- /dev/null +++ b/spring-core/src/main/java/org/springframework/cglib/core/SpringNamingPolicy.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cglib.core; + +/** + * Custom extension of CGLIB's {@link DefaultNamingPolicy}, modifying + * the tag in generated class names from "ByCGLIB" to "BySpringCGLIB". + * + *

This is primarily designed to avoid clashes between a regular CGLIB + * version (used by some other library) and Spring's embedded variant, + * in case the same class happens to get proxied for different purposes. + * + * @author Juergen Hoeller + * @since 3.2.8 + */ +public class SpringNamingPolicy extends DefaultNamingPolicy { + + public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy(); + + @Override + protected String getTag() { + return "BySpringCGLIB"; + } + +} diff --git a/spring-core/src/main/java/org/springframework/cglib/transform/impl/MemorySafeUndeclaredThrowableStrategy.java b/spring-core/src/main/java/org/springframework/cglib/transform/impl/MemorySafeUndeclaredThrowableStrategy.java index 7de1b04ab2f..7a98ece88a6 100644 --- a/spring-core/src/main/java/org/springframework/cglib/transform/impl/MemorySafeUndeclaredThrowableStrategy.java +++ b/spring-core/src/main/java/org/springframework/cglib/transform/impl/MemorySafeUndeclaredThrowableStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,20 +25,22 @@ import org.springframework.cglib.transform.MethodFilterTransformer; import org.springframework.cglib.transform.TransformingClassGenerator; /** - * Memory safe variant of {@link UndeclaredThrowableStrategy} ported from the latest - * as yet unreleased cglib code. + * Memory-safe variant of {@link UndeclaredThrowableStrategy} ported from the latest + * as yet unreleased CGLIB code. + * + * @author Phillip Webb + * @since 3.2.4 */ public class MemorySafeUndeclaredThrowableStrategy extends DefaultGeneratorStrategy { private static final MethodFilter TRANSFORM_FILTER = new MethodFilter() { - public boolean accept(int access, String name, String desc, String signature, - String[] exceptions) { + public boolean accept(int access, String name, String desc, String signature, String[] exceptions) { return !TypeUtils.isPrivate(access) && name.indexOf('$') < 0; } }; - private Class wrapper; + private Class wrapper; public MemorySafeUndeclaredThrowableStrategy(Class wrapper) { @@ -51,4 +53,5 @@ public class MemorySafeUndeclaredThrowableStrategy extends DefaultGeneratorStrat tr = new MethodFilterTransformer(TRANSFORM_FILTER, tr); return new TransformingClassGenerator(cg, tr); } + }