提交 8c4e3725 编写于 作者: J Juergen Hoeller

Introduced SpringNamingPolicy for CGLIB

Issue: SPR-11398
上级 522d136b
/*
* 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;
......@@ -45,7 +46,7 @@ import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;
import org.springframework.cglib.transform.impl.MemorySafeUndeclaredThrowableStrategy;
import org.springframework.cglib.transform.impl.UndeclaredThrowableStrategy;
import org.springframework.core.SmartClassLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
......@@ -183,19 +184,19 @@ 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 UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackTypes(types);
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.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);
......
/*
* 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;
......@@ -107,6 +107,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
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());
}
......
/*
* 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.
......@@ -34,6 +34,7 @@ import org.springframework.beans.factory.support.SimpleInstantiationStrategy;
import org.springframework.cglib.core.ClassGenerator;
import org.springframework.cglib.core.Constants;
import org.springframework.cglib.core.DefaultGeneratorStrategy;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Enhancer;
......@@ -67,6 +68,8 @@ class ConfigurationClassEnhancer {
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
private static final DefaultGeneratorStrategy GENERATOR_STRATEGY = new BeanFactoryAwareGeneratorStrategy();
private static final String BEAN_FACTORY_FIELD = "$$beanFactory";
private static final Log logger = LogFactory.getLog(ConfigurationClassEnhancer.class);
......@@ -105,22 +108,10 @@ class ConfigurationClassEnhancer {
enhancer.setSuperclass(superclass);
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(GENERATOR_STRATEGY);
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
enhancer.setStrategy(new DefaultGeneratorStrategy() {
@Override
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
@Override
public void end_class() {
declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD,
Type.getType(BeanFactory.class), null);
super.end_class();
}
};
return new TransformingClassGenerator(cg, transformer);
}
});
return enhancer;
}
......@@ -200,37 +191,27 @@ class ConfigurationClassEnhancer {
/**
* Intercepts the invocation of any {@link DisposableBean#destroy()} on @Configuration
* class instances for the purpose of de-registering CGLIB callbacks. This helps avoid
* garbage collection issues. See SPR-7901.
* @see EnhancedConfiguration
* Custom extension of CGLIB's DefaultGeneratorStrategy, introducing a {@link BeanFactory} field.
*/
private static class DisposableBeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
private static class BeanFactoryAwareGeneratorStrategy extends DefaultGeneratorStrategy {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Enhancer.registerStaticCallbacks(obj.getClass(), null);
// Does the actual (non-CGLIB) superclass actually implement DisposableBean?
// If so, call its dispose() method. If not, just exit.
if (DisposableBean.class.isAssignableFrom(obj.getClass().getSuperclass())) {
return proxy.invokeSuper(obj, args);
}
return null;
}
@Override
public boolean isMatch(Method candidateMethod) {
return candidateMethod.getName().equals("destroy") &&
candidateMethod.getParameterTypes().length == 0 &&
DisposableBean.class.isAssignableFrom(candidateMethod.getDeclaringClass());
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
ClassEmitterTransformer transformer = new ClassEmitterTransformer() {
@Override
public void end_class() {
declare_field(Constants.ACC_PUBLIC, BEAN_FACTORY_FIELD, Type.getType(BeanFactory.class), null);
super.end_class();
}
};
return new TransformingClassGenerator(cg, transformer);
}
}
/**
* Intercepts the invocation of any
* {@link BeanFactoryAware#setBeanFactory(BeanFactory)} on {@code @Configuration}
* class instances for the purpose of recording the {@link BeanFactory}.
* Intercepts the invocation of any {@link BeanFactoryAware#setBeanFactory(BeanFactory)} on
* {@code @Configuration} class instances for the purpose of recording the {@link BeanFactory}.
* @see EnhancedConfiguration
*/
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {
......@@ -387,6 +368,7 @@ class ConfigurationClassEnhancer {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(fbClass);
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
......@@ -404,7 +386,8 @@ class ConfigurationClassEnhancer {
Assert.state(field != null, "Unable to find generated bean factory field");
Object beanFactory = ReflectionUtils.getField(field, enhancedConfigInstance);
Assert.state(beanFactory != null, "BeanFactory has not been injected into @Configuration class");
Assert.state(beanFactory instanceof ConfigurableBeanFactory, "Injected BeanFactory is not a ConfigurableBeanFactory");
Assert.state(beanFactory instanceof ConfigurableBeanFactory,
"Injected BeanFactory is not a ConfigurableBeanFactory");
return (ConfigurableBeanFactory) beanFactory;
}
......@@ -414,4 +397,32 @@ class ConfigurationClassEnhancer {
}
}
/**
* Intercepts the invocation of any {@link DisposableBean#destroy()} on @Configuration
* class instances for the purpose of de-registering CGLIB callbacks. This helps avoid
* garbage collection issues. See SPR-7901.
* @see EnhancedConfiguration
*/
private static class DisposableBeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Enhancer.registerStaticCallbacks(obj.getClass(), null);
// Does the actual (non-CGLIB) superclass actually implement DisposableBean?
// If so, call its dispose() method. If not, just exit.
if (DisposableBean.class.isAssignableFrom(obj.getClass().getSuperclass())) {
return proxy.invokeSuper(obj, args);
}
return null;
}
@Override
public boolean isMatch(Method candidateMethod) {
return candidateMethod.getName().equals("destroy") &&
candidateMethod.getParameterTypes().length == 0 &&
DisposableBean.class.isAssignableFrom(candidateMethod.getDeclaringClass());
}
}
}
/*
* 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".
*
* <p>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";
}
}
/*
* Copyright 2002-2013 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.transform.impl;
import org.springframework.cglib.core.ClassGenerator;
import org.springframework.cglib.core.DefaultGeneratorStrategy;
import org.springframework.cglib.core.TypeUtils;
import org.springframework.cglib.transform.ClassTransformer;
import org.springframework.cglib.transform.MethodFilter;
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.
*/
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) {
return !TypeUtils.isPrivate(access) && name.indexOf('$') < 0;
}
};
private Class<?> wrapper;
public MemorySafeUndeclaredThrowableStrategy(Class<?> wrapper) {
this.wrapper = wrapper;
}
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
ClassTransformer tr = new UndeclaredThrowableTransformer(wrapper);
tr = new MethodFilterTransformer(TRANSFORM_FILTER, tr);
return new TransformingClassGenerator(cg, tr);
}
}
/*
* 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.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.target.EmptyTargetSource;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.Factory;
......@@ -72,16 +73,15 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
public static final String MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME = "mvcUriComponentsContributor";
private static final CompositeUriComponentsContributor defaultUriComponentsContributor;
private static final Log logger = LogFactory.getLog(MvcUriComponentsBuilder.class);
private static final ObjenesisStd objenesis = new ObjenesisStd(true);
private static final PathMatcher pathMatcher = new AntPathMatcher();
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private static final ObjenesisStd objenesis = new ObjenesisStd(true);
private static final Log logger = LogFactory.getLog(MvcUriComponentsBuilder.class);
private static final CompositeUriComponentsContributor defaultUriComponentsContributor;
static {
defaultUriComponentsContributor = new CompositeUriComponentsContributor(
......@@ -341,7 +341,8 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
else {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(type);
enhancer.setInterfaces(new Class<?>[]{MethodInvocationInfo.class});
enhancer.setInterfaces(new Class<?>[] {MethodInvocationInfo.class});
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class);
Factory factory = (Factory) objenesis.newInstance(enhancer.createClass());
factory.setCallbacks(new Callback[] {interceptor});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册