Skip to content

Commit 034cf6a

Browse files
committed
Merge pull request #28531 from dreis2211
* pr/28531: Polish contribution Avoid duplicate AOP proxy class definition with FilteredClassLoader Closes gh-28531
2 parents cd5508a + 4304eea commit 034cf6a

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/FilteredClassLoader.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,12 +20,14 @@
2020
import java.io.InputStream;
2121
import java.net.URL;
2222
import java.net.URLClassLoader;
23+
import java.security.ProtectionDomain;
2324
import java.util.Arrays;
2425
import java.util.Collection;
2526
import java.util.Collections;
2627
import java.util.Enumeration;
2728
import java.util.function.Predicate;
2829

30+
import org.springframework.core.SmartClassLoader;
2931
import org.springframework.core.io.ClassPathResource;
3032

3133
/**
@@ -37,7 +39,7 @@
3739
* @author Roy Jacobs
3840
* @since 2.0.0
3941
*/
40-
public class FilteredClassLoader extends URLClassLoader {
42+
public class FilteredClassLoader extends URLClassLoader implements SmartClassLoader {
4143

4244
private final Collection<Predicate<String>> classesFilters;
4345

@@ -129,6 +131,16 @@ public InputStream getResourceAsStream(String name) {
129131
return super.getResourceAsStream(name);
130132
}
131133

134+
@Override
135+
public Class<?> publicDefineClass(String name, byte[] b, ProtectionDomain protectionDomain) {
136+
for (Predicate<String> filter : this.classesFilters) {
137+
if (filter.test(name)) {
138+
throw new IllegalArgumentException(String.format("Defining class with name %s is not supported", name));
139+
}
140+
}
141+
return defineClass(name, b, 0, b.length, protectionDomain);
142+
}
143+
132144
/**
133145
* Filter to restrict the classes that can be loaded.
134146
*/

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/FilteredClassLoaderTests.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626

2727
import static org.assertj.core.api.Assertions.assertThat;
2828
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
29+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
2930

3031
/**
3132
* Tests for {@link FilteredClassLoader}.
@@ -111,4 +112,13 @@ void loadResourceAsStreamWhenNotFilteredShouldLoadResource() throws Exception {
111112
}
112113
}
113114

115+
@Test
116+
void publicDefineClassWhenFilteredThrowsException() throws Exception {
117+
Class<FilteredClassLoaderTests> hiddenClass = FilteredClassLoaderTests.class;
118+
try (FilteredClassLoader classLoader = new FilteredClassLoader(hiddenClass)) {
119+
assertThatIllegalArgumentException()
120+
.isThrownBy(() -> classLoader.publicDefineClass(hiddenClass.getName(), new byte[] {}, null));
121+
}
122+
}
123+
114124
}

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/runner/AbstractApplicationContextRunnerTests.java

+37
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
import org.junit.jupiter.api.Test;
2525

2626
import org.springframework.beans.factory.BeanDefinitionStoreException;
27+
import org.springframework.beans.factory.annotation.Autowired;
2728
import org.springframework.boot.context.annotation.UserConfigurations;
29+
import org.springframework.boot.context.properties.ConfigurationProperties;
30+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2831
import org.springframework.boot.test.context.FilteredClassLoader;
2932
import org.springframework.boot.test.context.assertj.ApplicationContextAssertProvider;
3033
import org.springframework.context.ConfigurableApplicationContext;
@@ -33,6 +36,7 @@
3336
import org.springframework.context.annotation.ConditionContext;
3437
import org.springframework.context.annotation.Conditional;
3538
import org.springframework.context.annotation.Configuration;
39+
import org.springframework.context.annotation.Lazy;
3640
import org.springframework.core.env.Environment;
3741
import org.springframework.core.type.AnnotatedTypeMetadata;
3842
import org.springframework.util.ClassUtils;
@@ -165,6 +169,15 @@ void runWithClassLoaderShouldSetClassLoaderOnConditionContext() {
165169
.run((context) -> assertThat(context).hasSingleBean(ConditionalConfig.class));
166170
}
167171

172+
@Test
173+
void consecutiveRunWithFilteredClassLoaderShouldHaveBeanWithLazyProperties() {
174+
get().withClassLoader(new FilteredClassLoader(Gson.class)).withUserConfiguration(LazyConfig.class)
175+
.run((context) -> assertThat(context).hasSingleBean(ExampleBeanWithLazyProperties.class));
176+
177+
get().withClassLoader(new FilteredClassLoader(Gson.class)).withUserConfiguration(LazyConfig.class)
178+
.run((context) -> assertThat(context).hasSingleBean(ExampleBeanWithLazyProperties.class));
179+
}
180+
168181
@Test
169182
void thrownRuleWorksWithCheckedException() {
170183
get().run((context) -> assertThatIOException().isThrownBy(() -> throwCheckedException("Expected message"))
@@ -241,6 +254,30 @@ static class ConditionalConfig {
241254

242255
}
243256

257+
@Configuration(proxyBeanMethods = false)
258+
@EnableConfigurationProperties(ExampleProperties.class)
259+
static class LazyConfig {
260+
261+
@Bean
262+
ExampleBeanWithLazyProperties exampleBeanWithLazyProperties() {
263+
return new ExampleBeanWithLazyProperties();
264+
}
265+
266+
}
267+
268+
static class ExampleBeanWithLazyProperties {
269+
270+
@Autowired
271+
@Lazy
272+
ExampleProperties exampleProperties;
273+
274+
}
275+
276+
@ConfigurationProperties
277+
public static class ExampleProperties {
278+
279+
}
280+
244281
static class FilteredClassLoaderCondition implements Condition {
245282

246283
@Override

0 commit comments

Comments
 (0)