Skip to content

Commit

Permalink
Reintroduce FastClass in CGLIB class names for @⁠Configuration classes
Browse files Browse the repository at this point in the history
Given a @⁠Configuration class named org.example.AppConfig which
contains @⁠Bean methods, in Spring Framework 5.3.x and previous
versions, the following classes were created when generating the CGLIB
proxy.

org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa
org.example.AppConfig$$FastClassBySpringCGLIB$$3fec86e
org.example.AppConfig$$EnhancerBySpringCGLIB$$fd7e9baa$$FastClassBySpringCGLIB$$82534900

Those class names indicate that 1 class was generated for the proxy for
the @⁠Configuration class itself and that 2 additional FastClass
classes were generated to support proxying of @⁠Bean methods in
superclasses.

However, since Spring Framework 6.0, the following classes are created
when generating the CGLIB proxy.

org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$1
org.example.AppConfig$$SpringCGLIB$$2

The above class names make it appear that 3 proxy classes are generated
for each @⁠Configuration class, which is misleading.

To address that and to align more closely with how such generated
classes were named in previous versions of the framework, this commit
modifies SpringNamingPolicy so that generated class names once again
include "FastClass" when the generated class is for a CGLIB FastClass
as opposed to the actual proxy for the @⁠Configuration class.

Consequently, with this commit the following classes are created when
generating the CGLIB proxy.

org.example.AppConfig$$SpringCGLIB$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$0
org.example.AppConfig$$SpringCGLIB$$FastClass$$1

Closes gh-31272
  • Loading branch information
sbrannen committed Sep 25, 2023
1 parent d17c75a commit 18456de
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,8 @@ void processAheadOfTimeWhenHasCglibProxyWriteProxyAndGenerateReflectionHints() t
applicationContext.registerBean(CglibConfiguration.class);
TestGenerationContext context = processAheadOfTime(applicationContext);
isRegisteredCglibClass(context, CglibConfiguration.class.getName() + "$$SpringCGLIB$$0");
isRegisteredCglibClass(context, CglibConfiguration.class.getName() + "$$SpringCGLIB$$1");
isRegisteredCglibClass(context, CglibConfiguration.class.getName() + "$$SpringCGLIB$$2");
isRegisteredCglibClass(context, CglibConfiguration.class.getName() + "$$SpringCGLIB$$FastClass$$0");
isRegisteredCglibClass(context, CglibConfiguration.class.getName() + "$$SpringCGLIB$$FastClass$$1");
}

private void isRegisteredCglibClass(TestGenerationContext context, String cglibClassName) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* in the classpath.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.2.8 / 6.0
*/
public final class SpringNamingPolicy implements NamingPolicy {
Expand All @@ -33,6 +34,8 @@ public final class SpringNamingPolicy implements NamingPolicy {

private static final String SPRING_LABEL = "$$SpringCGLIB$$";

private static final String FAST_CLASS_SUFFIX = "FastClass$$";


private SpringNamingPolicy() {
}
Expand All @@ -55,6 +58,13 @@ else if (prefix.startsWith("java.") || prefix.startsWith("javax.")) {
base = prefix + SPRING_LABEL;
}

// When the generated class name is for a FastClass, the source is
// "org.springframework.cglib.reflect.FastClass".
boolean isFastClass = (source != null && source.endsWith(".FastClass"));
if (isFastClass && !prefix.contains(FAST_CLASS_SUFFIX)) {
base += FAST_CLASS_SUFFIX;
}

int index = 0;
String attempt = base + index;
while (names.evaluate(attempt)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import org.junit.jupiter.api.Test;

import org.springframework.cglib.reflect.FastClass;

import static org.assertj.core.api.Assertions.assertThat;

/**
Expand Down Expand Up @@ -67,6 +69,15 @@ void prefixContainingSpringLabel() {
assertThat(getClassName(generated1)).isEqualTo(generated2);
}

@Test
void fastClass() {
String prefix = "example.MyComponent";
String source = FastClass.class.getName();
assertThat(getClassName(prefix, "a.b.c", null)).isEqualTo("example.MyComponent$$SpringCGLIB$$0");
assertThat(getClassName(prefix, source, null)).isEqualTo("example.MyComponent$$SpringCGLIB$$FastClass$$0");
assertThat(getClassName(prefix, source, null)).isEqualTo("example.MyComponent$$SpringCGLIB$$FastClass$$1");
}

private String getClassName(String prefix) {
return getClassName(prefix, null, null);
}
Expand Down

0 comments on commit 18456de

Please sign in to comment.