- 1.自动装配简述
- 2.如何排除自动装配功能
- 2.1启动类注解设置需要排除的自动装配类
- 2.2在配置文件中指定需要排除的类
- 3.问题描述和寻找方案
- 4.解决方案
spring boot中一个重要功能就是自动装配。简单来说就是:在我们开发的项目中,引入相关功能的jar包。spring boot会将其功能自动注入进来,不需要额外的配置。当然,这是因为配置提供了很多比较公用的缺省值。举例spring boot项目中加入如下依赖,即可使项目接入本地启动的redis。这就是因为有着自动装配。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
2.如何排除自动装配功能
有些场景下我们可能需要加入相关依赖,但是又不一定用到自动装配。面对这种情况,主要提供了两种办法。
2.1启动类注解设置需要排除的自动装配类import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SysApplication {
public static void main(String[] args) {
SpringApplication.run(SysApplication.class, args);
}
}
如果项目没有直接引用依赖的话,可以使用注解的excludeName属性,传入类的全名。
EnableAutoConfiguration注解同理。
spring.autoconfigure.exclude = org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
# 或者这样
spring.autoconfigure.exclude[0] = org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
如果这两种方式满足的话,下面可以不看了。
3.问题描述和寻找方案最近工作中遇到了上面两种方法不能解决的情况。大概场景是这样的:
我负责公司内部开发框架的开发。现在提供一个数据源的功能包,因为一些情况。不能让项目引入就直接使用,而是希望通过注解的形式开启使用。
所以希望引入内部开发框架中依赖的时候不带入自动装配的内容。希望做到的就是一个依赖+一个注解开启使用。额外的什么排除自动装配之类,全部封装在这个数据源的功能包中。
上代码:这里是org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry的内容
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 这里获取到了所有需要自动装配的类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
// 重点在这里,这里获取需要排除集合
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
这里是org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getExclusions
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
Set<String> excluded = new LinkedHashSet<>();
// 这里两行获取到了启动类上指定的exclude和excludeName,也就是2.1描述的方式
excluded.addAll(asList(attributes, "exclude"));
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
// 这里读取配置文件中spring.autoconfigure.exclude的信息,也就是2.2描述的方式
excluded.addAll(getExcludeAutoConfigurationsProperty());
return excluded;
}
4.解决方案
通过自动装配的源码发现,好像也就是这两种方式。分析一下:启动类的方式是依赖于编码的,不容易在这里动态加东西。最好还是通过动态修改配置文件。
整体思路:
- 获取到原配置文件内容
- 增加需要排除的类
- 保存新的高优先级配置文件
工具包代码:
resources/META-INF/spring.factories
org.springframework.boot.env.EnvironmentPostProcessor=\
com.dong.common.data.init.ExcludeEnvironmentPostProcessor
ExcludeEnvironmentPostProcessor类
import cn.hutool.core.collection.CollectionUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import java.util.*;
@Configuration
public class ExcludeEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String key = "spring.autoconfigure.exclude";
Binder binder = Binder.get(environment);
List<String> exList = new ArrayList<>();
// 1 先获取到原配置文件的信息。这里参考的AutoConfigurationImportSelector#getExcludeAutoConfigurationsProperty
List<String> stringList = (List)binder.bind(key, String[].class).map(Arrays::asList).orElse(Collections.emptyList());
exList.addAll(stringList);
// 2 增加需要排除的类
exList.add("org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration");
MutablePropertySources m = environment.getPropertySources();
Properties p = new Properties();
p.put(key, CollectionUtil.join(exList,","));
// 3 保存新的配置文件
m.addFirst(new PropertiesPropertySource("commonDataProperties", p));
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
用到的其他依赖
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.7.3version>
dependency>
好了,大功告成。工具包中加入这些代码,会自动排除DataSourceAutoConfiguration的自动装配。最后在需要的地方再引入一下DataSourceAutoConfiguration就可以了
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)