JAVASpring

SpringBoot工程无法扫描Jar包中的组件(e.g. @Configuration,@Component,etc…)

背景


这是我在学习SpringSecurity组件时出现的一个问题。大致情况就是

我有两个工程:

  • security-demo
    这是一个springboot工程
  • security-browser
    这是一个spring工程,用于作为Jar包给security-demo工程使用

配置情况:

security-browser工程中有个config配置类

//这是一个Spring Java配置类
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
	```
	//内容不重要,总之内部需要实现某些功能
}

security-demo的pom中依赖了security-browser的jar包

<dependency>
   <groupId>com.snailmann.security</groupId>
   <artifactId>security-browser</artifactId>
   <version>${project.version}</version>
</dependency>

期望:
我的期望是当我启动security-demo项目,security-browser中的BrowserSecurityConfig类会被注入到Spring容器中,完成某些功能。

问题:

问题就是BrowserSecurityConfig类并没有被security-demo项目的Spring容器实例化,因为Spring容器中并没有BrowserSecurityConfig,所以导致我要在BrowserSecurityConfig实现的某些功能失效

分析


  • security-browser工程是否没有正确打包
  • security-demo并没有引入security-browser的jar包
  • Configuration配置错误
  • Spring不支持扫描Jar包组件
  • 是否少配置了什么东西?
  • etc…

解决方案


经过实践,大部分的问题都被排除掉了,几个小时也过去了。最后面,某些资料引起了我的注意。大致就是有人遇到了SpringBoot工程无法扫描Jar包中组件的问题,So…

How to make Spring’s @ComponentScan search components in included JARs

方法一

因为Jar包中的Configuration类没有被注入,所以我们可以在Demo项目中手工注入,通过在demo模块中的Configuration类中声明

  @Bean
    public BrowserSecurityConfig getBrowserSecurityConfig(){
        return new BrowserSecurityConfig();
    }


虽然这样可以实现,但这种方式并不好,相当于声明了两次

方法二

另一种方式就从@ComponentScan注解下手,但因为对这个注解的理解还不够深入,所以暂且得出这一个简略的方法

@ComponentScan(basePackages={"com.snailmann.security.demo","com.snailmann.security.browser"})
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

因为在SpringBoot的默认扫描中,貌似是不会扫描Jar包中的组件,所以我们得显示的声明Spring容器要扫描的路径。这就包括了本项目的路径,以及要扫描的Jar包的路径。com.snailmann.security.demo是demo项目的路径,com.snailmann.security.browser是Jar包的路径

当然我们可以看到的是如果两个项目的主路径几乎相同,我们可以简写成

@ComponentScan(basePackages={"com.snailmann.security"})
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}