Skip to content

Commit 00e8937

Browse files
author
Dave Syer
committed
Allow spring.main.sources to override only if uninitialized
The problem this change fixes is that spring.main.sources would always be bound to SpringApplication.sources when provided in a properties file even if SpringApplication.run() is called directly with sources. This led to confusion with users saying that their sources were not working where in fact they weren't even being used. There would be more than one way to approach this problem, but we have chosen for now to ignore spring.main.sources completely if the SpringApplication constructor was already called with explicit non-empty sources. It might be preferable, if possible, to only ignore its value in an external properties file (allowing command line or System properties to override). If we want to change the behaviour again, I suggest a new story should be created. [Fixes #54185750] [bs-255]
1 parent 39425c8 commit 00e8937

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ private int load(Package source) {
155155

156156
private int load(CharSequence source) {
157157
try {
158-
return load(Class.forName(source.toString()));
158+
// Use class utils so that period separated nested class names work
159+
return load(ClassUtils.forName(source.toString(), null));
159160
}
160161
catch (ClassNotFoundException ex) {
161162
// swallow exception and continue

spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ public class SpringApplication {
161161

162162
private String[] defaultCommandLineArgs;
163163

164+
private boolean sourcesInitialized = false;
165+
164166
/**
165167
* Crate a new {@link SpringApplication} instance. The application context will load
166168
* beans from the specified sources (see {@link SpringApplication class-level}
@@ -190,7 +192,8 @@ public SpringApplication(ResourceLoader resourceLoader, Object... sources) {
190192
}
191193

192194
private void initialize(Object[] sources) {
193-
if (sources != null) {
195+
if (sources != null && sources.length > 0) {
196+
this.sourcesInitialized = true;
194197
this.sources.addAll(Arrays.asList(sources));
195198
}
196199
this.webEnvironment = deduceWebEnvironment();
@@ -576,6 +579,9 @@ public Set<Object> getSources() {
576579
* @see #SpringApplication(Object...)
577580
*/
578581
public void setSources(Set<Object> sources) {
582+
if (this.sourcesInitialized) {
583+
return;
584+
}
579585
Assert.notNull(sources, "Sources must not be null");
580586
this.sources = new LinkedHashSet<Object>(sources);
581587
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2012-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot;
18+
19+
import org.junit.Test;
20+
import org.springframework.beans.factory.annotation.Autowired;
21+
import org.springframework.context.ApplicationContext;
22+
import org.springframework.context.annotation.Bean;
23+
import org.springframework.context.annotation.Configuration;
24+
import org.springframework.context.annotation.Primary;
25+
26+
import static org.junit.Assert.assertEquals;
27+
28+
/**
29+
* @author Dave Syer
30+
*/
31+
public class OverrideSourcesTests {
32+
33+
@Test
34+
public void beanInjectedToMainConfiguration() {
35+
ApplicationContext context = SpringApplication.run(
36+
new Object[] { MainConfiguration.class },
37+
new String[] { "--spring.main.web_environment=false" });
38+
assertEquals("foo", context.getBean(Service.class).bean.name);
39+
}
40+
41+
@Test
42+
public void primaryBeanInjectedProvingSourcesNotOverridden() {
43+
ApplicationContext context = SpringApplication
44+
.run(new Object[] { MainConfiguration.class, TestConfiguration.class },
45+
new String[] { "--spring.main.web_environment=false",
46+
"--spring.main.sources=org.springframework.boot.OverrideSourcesTests.MainConfiguration" });
47+
assertEquals("bar", context.getBean(Service.class).bean.name);
48+
}
49+
50+
@Configuration
51+
protected static class TestConfiguration {
52+
53+
@Bean
54+
@Primary
55+
public TestBean another() {
56+
return new TestBean("bar");
57+
}
58+
59+
}
60+
61+
@Configuration
62+
protected static class MainConfiguration {
63+
64+
@Bean
65+
public TestBean first() {
66+
return new TestBean("foo");
67+
}
68+
69+
@Bean
70+
public Service Service() {
71+
return new Service();
72+
}
73+
74+
}
75+
76+
protected static class Service {
77+
@Autowired
78+
private TestBean bean;
79+
}
80+
81+
protected static class TestBean {
82+
83+
private String name;
84+
85+
public TestBean(String name) {
86+
this.name = name;
87+
}
88+
89+
}
90+
}

0 commit comments

Comments
 (0)