ASM ClassWriter uses application ClassLoader for its getCommonSuperClass check
Issue: SPR-13695
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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,6 +25,9 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.cglib.core.ClassGenerator;
|
||||
import org.springframework.cglib.core.DefaultGeneratorStrategy;
|
||||
import org.springframework.cglib.core.SpringNamingPolicy;
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.CallbackFilter;
|
||||
@@ -141,6 +144,10 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(beanDefinition.getBeanClass());
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
if (this.owner instanceof ConfigurableBeanFactory) {
|
||||
ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
|
||||
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
|
||||
}
|
||||
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
|
||||
enhancer.setCallbackTypes(CALLBACK_TYPES);
|
||||
return enhancer.createClass();
|
||||
@@ -178,6 +185,52 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CGLIB GeneratorStrategy variant which exposes the application ClassLoader
|
||||
* as thread context ClassLoader for the time of class generation
|
||||
* (in order for ASM to pick it up when doing common superclass resolution).
|
||||
*/
|
||||
private static class ClassLoaderAwareGeneratorStrategy extends DefaultGeneratorStrategy {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public ClassLoaderAwareGeneratorStrategy(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generate(ClassGenerator cg) throws Exception {
|
||||
if (this.classLoader == null) {
|
||||
return super.generate(cg);
|
||||
}
|
||||
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader threadContextClassLoader;
|
||||
try {
|
||||
threadContextClassLoader = currentThread.getContextClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Cannot access thread context ClassLoader - falling back...
|
||||
return super.generate(cg);
|
||||
}
|
||||
|
||||
boolean overrideClassLoader = !this.classLoader.equals(threadContextClassLoader);
|
||||
if (overrideClassLoader) {
|
||||
currentThread.setContextClassLoader(this.classLoader);
|
||||
}
|
||||
try {
|
||||
return super.generate(cg);
|
||||
}
|
||||
finally {
|
||||
if (overrideClassLoader) {
|
||||
// Reset original thread context ClassLoader.
|
||||
currentThread.setContextClassLoader(threadContextClassLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CGLIB callback for filtering method interception behavior.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user