1、背景
在有些时候,不同环境可能需要用代码不同模块的能力,但是不同环境的项目包是一致的。这块我们想到的最简单的办法是在maven打包的时候打不同的模块,但是这样往往需要出多个包,虽然这种方式是正路但运维同学嫌麻烦。第二种方式是在spring扫包时候排除指定的排除的类或者模块,针对模块来说则需要自己实现,作者经过测试发现这种方式存在很大的问题,网上大面积是这种解决方案,基本都是乱抄。第三种方式则是采用spring的后置处理器实现。下边作者把这几种方式的实现大概写下。
2、maven打包方式
mvn package a b c
这种方式通过传不同的abc进行出包,但不是我们想要的方式。
3、使用@ConponentScan注解
现在一般项目都用Springboot开发,直接用@SpringBootApplication即可,该注解提供了baseScan的路劲配置能力,但是在exclude掉不想要的模块时就显得力不从心。我们打开@SprinbootApplication注解时发现其为三个注解的整合,其参数basescan**本质就是@ConponentScan注解,但是@SpringBootApplication无法定制化exclude能力,所以我们将@SpringBootApplication里的三个注解提炼出来,替代@SpringbootApplication
然后改造如下:
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(includeFilters = @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class))
public static void main(string[] args){
Springbootapplication.run(a.class);
}
注意这块作者是直接用手机写的,全凭记忆,把大概过程记录一下。
这块的FilterType类型有以下
FilterType.ANNOTATION:按照注解过滤
FilterType.ASSIGNABLE_TYPE:按照给定的类型,指定具体的类,子类也会被扫描到
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:正则
FilterType.CUSTOM:自定义规则
useDefaultFilters: 配置是否开启可以对加@Component,@Repository,@Service,@Controller注解的类进行检测, 针对Java8 语法可以指定多个@ComponentScan
我们要排除包则需要用CUSTOM类型去自定义实现。
这里作者直接用伪代码开写✍🏻
public class TypeExcludeFilter implement TypeFilter,EnvironmentAware{
private string[] exclude;
public boolean match(元参数,源参数工厂){
通过源参数拿到类class信息
通过class拿到注解信息
如果没有注解则直接返回true
循环检测类路劲是否在配置项的路劲中如果检测到则返回false,标记扫包的时候不要注册此类
}
public void setEnvireonment(配置对象)
获取要排除的包路劲
将包路径转化为exclude
}
通过上边伪代码的描述,似乎这种方式能解决问题,但是要判断是否有注解才能继续,否则很多类都被误杀,对于项目很大的情况下,这种方式让人很头大,完全是人肉模式。所以这种方式只能是最差的方式。
3、通过Spring的beanRegisryPostProcesser进行移除。
这种方式在bean真正实例化之前进行操作,避免项目启动一些资源类直接初始化产生的问题,个人觉得这种方式是比较可靠并且维护成本也低。因为手机打字,这块作者直接伪代码截图了。