Warn on @ComponentScan of default package
Add ConfigurationWarningsApplicationContextInitializer to report warnings for common configuration mistakes. Currently the initializer will log a warning if @ComponentScan is used on a @Configuration class in the "default" package. Fixes gh-2050
This commit is contained in:
parent
447c9ff204
commit
1a5735191f
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link ApplicationContextInitializer} to report warnings for common misconfiguration
|
||||
* mistakes.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class ConfigurationWarningsApplicationContextInitializer implements
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
private static Log logger = LogFactory
|
||||
.getLog(ConfigurationWarningsApplicationContextInitializer.class);
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext context) {
|
||||
context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(
|
||||
getChecks()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the checks that should be applied.
|
||||
* @return the checks to apply
|
||||
*/
|
||||
protected Check[] getChecks() {
|
||||
return new Check[] { new ComponentScanDefaultPackageCheck() };
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionRegistryPostProcessor} to report warnings.
|
||||
*/
|
||||
protected final static class ConfigurationWarningsPostProcessor implements
|
||||
PriorityOrdered, BeanDefinitionRegistryPostProcessor {
|
||||
|
||||
private Check[] checks;
|
||||
|
||||
public ConfigurationWarningsPostProcessor(Check[] checks) {
|
||||
this.checks = checks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
|
||||
throws BeansException {
|
||||
for (Check check : this.checks) {
|
||||
String message = check.getWarning(registry);
|
||||
if (StringUtils.hasLength(message)) {
|
||||
warn(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void warn(String message) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("\n\n** WARNING ** : " + message + "\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A single check that can be applied.
|
||||
*/
|
||||
protected static interface Check {
|
||||
|
||||
/**
|
||||
* Returns a warning if the check fails or {@code null} if there are no problems.
|
||||
* @param registry the {@link BeanDefinitionRegistry}
|
||||
* @return a warning message or {@code null}
|
||||
*/
|
||||
String getWarning(BeanDefinitionRegistry registry);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Check} for {@code @ComponentScan} on the default package.
|
||||
*/
|
||||
protected static class ComponentScanDefaultPackageCheck implements Check {
|
||||
|
||||
@Override
|
||||
public String getWarning(BeanDefinitionRegistry registry) {
|
||||
if (isComponentScanningDefaultPackage(registry)) {
|
||||
return "Your ApplicationContext is unlikely to start due to a "
|
||||
+ "@ComponentScan of the default package.";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isComponentScanningDefaultPackage(BeanDefinitionRegistry registry) {
|
||||
String[] names = registry.getBeanDefinitionNames();
|
||||
for (String name : names) {
|
||||
BeanDefinition definition = registry.getBeanDefinition(name);
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition) definition;
|
||||
if (isScanningDefaultPackage(annotatedDefinition.getMetadata())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isScanningDefaultPackage(AnnotationMetadata metadata) {
|
||||
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata
|
||||
.getAnnotationAttributes(ComponentScan.class.getName(), true));
|
||||
if (attributes != null && hasNoScanPackageSpecified(attributes)) {
|
||||
if (isInDefaultPackage(metadata.getClassName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasNoScanPackageSpecified(AnnotationAttributes attributes) {
|
||||
return isAllEmpty(attributes, "value", "basePackages", "basePackageClasses");
|
||||
}
|
||||
|
||||
private boolean isAllEmpty(AnnotationAttributes attributes, String... names) {
|
||||
for (String name : names) {
|
||||
if (!ObjectUtils.isEmpty(attributes.getStringArray(name))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isInDefaultPackage(String className) {
|
||||
String packageName = ClassUtils.getPackageName(className);
|
||||
return StringUtils.isEmpty(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ org.springframework.boot.context.event.EventPublishingRunListener
|
|||
|
||||
# Application Context Initializers
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
|
||||
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
|
||||
org.springframework.boot.context.config.DelegatingApplicationContextInitializer
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ public class SpringApplicationBuilderTests {
|
|||
SpringApplicationBuilder application = new SpringApplicationBuilder(
|
||||
ExampleConfig.class).web(false);
|
||||
this.context = application.run();
|
||||
assertEquals(2, application.application().getInitializers().size());
|
||||
assertEquals(3, application.application().getInitializers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -247,7 +247,7 @@ public class SpringApplicationBuilderTests {
|
|||
SpringApplicationBuilder application = new SpringApplicationBuilder(
|
||||
ExampleConfig.class).child(ChildConfig.class).web(false);
|
||||
this.context = application.run();
|
||||
assertEquals(3, application.application().getInitializers().size());
|
||||
assertEquals(4, application.application().getInitializers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -261,7 +261,7 @@ public class SpringApplicationBuilderTests {
|
|||
}
|
||||
});
|
||||
this.context = application.run();
|
||||
assertEquals(3, application.application().getInitializers().size());
|
||||
assertEquals(4, application.application().getInitializers().size());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ComponentScanDefaultPackageCheck;
|
||||
import org.springframework.boot.context.configwarnings.InDefaultPackageConfiguration;
|
||||
import org.springframework.boot.context.configwarnings.InDefaultPackageWithBasePackageClassesConfiguration;
|
||||
import org.springframework.boot.context.configwarnings.InDefaultPackageWithBasePackagesConfiguration;
|
||||
import org.springframework.boot.context.configwarnings.InDefaultPackageWithMetaAnnotationConfiguration;
|
||||
import org.springframework.boot.context.configwarnings.InDefaultPackageWithValueConfiguration;
|
||||
import org.springframework.boot.context.configwarnings.InDefaultPackageWithoutScanConfiguration;
|
||||
import org.springframework.boot.context.configwarnings.InRealPackageConfiguration;
|
||||
import org.springframework.boot.test.OutputCapture;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationWarningsApplicationContextInitializer}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ConfigurationWarningsApplicationContextInitializerTests {
|
||||
|
||||
private static final String SCAN_WARNING = "Your ApplicationContext is unlikely to "
|
||||
+ "start due to a @ComponentScan of the default package";
|
||||
|
||||
@Rule
|
||||
public OutputCapture output = new OutputCapture();
|
||||
|
||||
@Test
|
||||
public void logWarningInDefaultPackage() {
|
||||
load(InDefaultPackageConfiguration.class);
|
||||
assertThat(this.output.toString(), containsString(SCAN_WARNING));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logWarningInDefaultPackageAndMetaAnnotation() {
|
||||
load(InDefaultPackageWithMetaAnnotationConfiguration.class);
|
||||
assertThat(this.output.toString(), containsString(SCAN_WARNING));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noLogIfInRealPackage() throws Exception {
|
||||
load(InRealPackageConfiguration.class);
|
||||
assertThat(this.output.toString(), not(containsString(SCAN_WARNING)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noLogWithoutComponetScanAnnotation() throws Exception {
|
||||
load(InDefaultPackageWithoutScanConfiguration.class);
|
||||
assertThat(this.output.toString(), not(containsString(SCAN_WARNING)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noLogIfHasValue() throws Exception {
|
||||
load(InDefaultPackageWithValueConfiguration.class);
|
||||
assertThat(this.output.toString(), not(containsString(SCAN_WARNING)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noLogIfHasBasePackages() throws Exception {
|
||||
load(InDefaultPackageWithBasePackagesConfiguration.class);
|
||||
assertThat(this.output.toString(), not(containsString(SCAN_WARNING)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noLogIfHasBasePackageClasses() throws Exception {
|
||||
load(InDefaultPackageWithBasePackageClassesConfiguration.class);
|
||||
assertThat(this.output.toString(), not(containsString(SCAN_WARNING)));
|
||||
}
|
||||
|
||||
private void load(Class<?> configClass) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
new TestConfigurationWarningsApplicationContextInitializer().initialize(context);
|
||||
context.register(configClass);
|
||||
try {
|
||||
context.refresh();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testable version of {@link ConfigurationWarningsApplicationContextInitializer}.
|
||||
*/
|
||||
public static class TestConfigurationWarningsApplicationContextInitializer extends
|
||||
ConfigurationWarningsApplicationContextInitializer {
|
||||
|
||||
@Override
|
||||
protected Check[] getChecks() {
|
||||
return new Check[] { new TestComponentScanDefaultPackageCheck() };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testable ComponentScanDefaultPackageCheck that doesn't need to use the default
|
||||
* package.
|
||||
*/
|
||||
static class TestComponentScanDefaultPackageCheck extends
|
||||
ComponentScanDefaultPackageCheck {
|
||||
|
||||
@Override
|
||||
protected boolean isInDefaultPackage(String className) {
|
||||
return className.contains("InDefault");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
public class InDefaultPackageConfiguration {
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import org.springframework.boot.context.configwarnings.nested.ExampleBean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackageClasses = ExampleBean.class)
|
||||
public class InDefaultPackageWithBasePackageClassesConfiguration {
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = "org.springframework.boot.context.configwarnings.nested")
|
||||
public class InDefaultPackageWithBasePackagesConfiguration {
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@MetaComponentScan
|
||||
public class InDefaultPackageWithMetaAnnotationConfiguration {
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("org.springframework.boot.context.configwarnings.nested")
|
||||
public class InDefaultPackageWithValueConfiguration {
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class InDefaultPackageWithoutScanConfiguration {
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
public class InRealPackageConfiguration {
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@ComponentScan
|
||||
public @interface MetaComponentScan {
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright 2012-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.boot.context.configwarnings.nested;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ExampleBean {
|
||||
|
||||
}
|
Loading…
Reference in New Issue