SpringBootApplication启动排除DataSourceAutoConfig。。。
项⽬引⽤了新版本mybatis-spring-boot-starter之后启动不起来,报错Cannot determine embedded database driver class for database type NONE,在⽹上搜索是需要在排除掉spring⾃⾝的org.springframework.boot.autoconfigure.jdbc.DataSourc 由于项⽬是采⽤spring boot框架,所以在@SpringBootApplication中exclude这个类即可:
改之前代码:
@EnableAutoConfiguration
@SpringBootApplication
@EnableDubbo(multipleConfig = true)
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).profiles("default").build(args).run(args);
}
}
添加DataSourceAutoConfiguration排除之后:
@EnableAutoConfiguration
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableDubbo(multipleConfig = true)
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).profiles("default").build(args).run(args);
}
}
本以为这样就成功了,改之后发现重新启动项⽬还是报⼀样的错误,就⽐较奇怪,⽹上都是这样解决的,⾃⼰这⾥却不⾏。
现在只能猜测是不是我上⾯这样配置没⽣效,根本没有排除掉DataSourceAutoConfiguration呢,然后去debug了下spring这块源码,看spring是如何到启动注解上要排除的类的。
最终到了这个类AnnotatedElementUtils#searchWithGetSemanticsInAnnotations⽅法,该⽅法是查该类上某个注解的定义配置的。
/**
* This method is invoked by {@link #searchWithGetSemantics} to perform
* the actual search within the supplied list of annotations.
* <p>This method should be invoked first with locally declared annotations
* and then subsequently with inherited annotations, thereby allowing
* local annotations to take precedence over inherited annotations.
* <p>The {@code metaDepth} parameter is explained in the
* {@link Processor#process process()} method of the {@link Processor} API.
* @param element the element that is annotated with the supplied
* annotations, used for contextual logging; may be {@code null} if unknown
* @param annotations the annotations to search in
* @param annotationType the annotation type to find
* @param annotationName the fully qualified class name of the annotation
* type to find (as an alternative to {@code annotationType})
* @param containerType the type of the container that holds repeatable
* annotations, or {@code null} if the annotation is not repeatable
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor (potentially {@code null})
* @since 4.2
*/
private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement element,
List<Annotation> annotations, Class<? extends Annotation> annotationType,
String annotationName, Class<? extends Annotation> containerType,
Processor<T> processor, Set<AnnotatedElement> visited, int metaDepth) {
// Search in annotations
// 这个for循环是在类上直接定义的注解上进⾏查指定的注解
for (Annotation annotation : annotations) {
Class<? extends Annotation> currentAnnotationType = annotation.annotationType();
if (!AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
if (currentAnnotationType == annotationType ||
processor.alwaysProcesses()) {
T result = processor.process(element, annotation, metaDepth);
if (result != null) {
if (processor.aggregates() && metaDepth == 0) {
}
else {
return result;
}
}
}
// Repeatable annotations in container?
else if (currentAnnotationType == containerType) {
for (Annotation contained : getRawAnnotationsFromContainer(element, annotation)) {
T result = processor.process(element, contained, metaDepth);
if (result != null) {
// No need to post-process since repeatable annotations within a
/
/ container cannot be composed annotations.
}
}
}
}
}
// Recursively search in meta-annotations
// 如果根据类上直接定义的注解去不到话,然后在遍历每⼀个注解,寻其通过继承关系得到的注解
for (Annotation annotation : annotations) {
Class<? extends Annotation> currentAnnotationType = annotation.annotationType();
if (!AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
T result = searchWithGetSemantics(currentAnnotationType, annotationType,
annotationName, containerType, processor, visited, metaDepth + 1);
if (result != null) {
processor.postProcess(element, annotation, result);
if (processor.aggregates() && metaDepth == 0) {
}
spring framework版本else {
return result;
}
}
}
}
return null;
}
拿我上⾯项⽬例⼦来说明,上⾯的代码我配置了@EnableAutoConfiguration和@SpringBootApplication两个注解,@SpringBootApplication⾥的exclude实际上使⽤的是@EnableAutoConfiguration⾥的exclude,所以当spring查EnableAutoConfigurat
知道了这个结论之后,项⽬正常启动,改动就很简单了:
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
@SpringBootApplication
@EnableDubbo(multipleConfig = true)
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).profiles("default").build(args).run(args);
}
}
或者:(推荐使⽤这种⽅式)
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableDubbo(multipleConfig = true)
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).profiles("default").build(args).run(args);
}
}
总结
通过查看上⾯spring代码⽅法注释也能得到结论,这个⽅法应该⾸先调⽤本地声明的注释然后⽤继承的注释,从⽽允许本地注解优先于继承的注解。
@SpringBootApplication是多个注解的组合,其中就已经包含了@EnableAutoConfiguration注解,所以引⽤了@SpringBootApplication注解之后不需要在⼿动注解@EnableAutoConfiguration
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论