解决SpringBoot多模块注⼊访问不到jar包中的Bean问题情景描述
⼀个聚合项⽬spring-security-tutorial,其中包括4个module,pom如下所⽰:
<project xmlns="/POM/4.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.jdkong.security</groupId>
<artifactId>spring-security-tutorial</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>``
<module>security-core</module>
<module>security-app</module>
<module>security-browser</module>
<module>security-demo</module>
</modules>
<!-- 其他部分省略-->
</project>
在此项⽬中,⼦项⽬security-browser是⼀个简单的maven项⽬,打成jar包,供security-demo使⽤,security-demo项⽬是⼀个springboot项⽬。
问题描述
在security-browser项⽬中⾃动注⼊了⼀个配置类,如下所⽰:
/**
* @author jdkong
*/
@Slf4j
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.and()
.authorizeRequests()
.anyRequest()
.
authenticated();
}
}
在security-demo中使⽤此配置类时,不起作⽤。
问题分析
导致此类问题的主要原因是,此类不在Spring Boot的组件扫描范围之内。
1. 关于 Spring Boot ⾃动注⼊及组件扫描
在平时使⽤ Spring Boot 时,常常会使⽤到@Configuration,@Contoller,@Service,@Component等注解,被添加这些注解的类,在 Spring Boot 启动时,会⾃动被 Spring 容器管理起来。
上⾯提到了,添加了⼀些注解的类会在Spring Boot 容器启动时,被加载到Spring 容器中。那么,组件扫描的作⽤就是:当Spring Boot 启动时,根据定义的扫描路径,把符合扫描规则的类装配到spring容器中。
2. Spring Boot 中 @ComponentScan
简单的介绍了@ComponentScan的基础作⽤,这个注解为我们使⽤提供了⼀些可⾃定义配置属性,先来看看
@ComponentScan注解源码:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
// 指定扫描包的位置(同:basePackages 属性),可以是单个路径,也可以是扫描的路径数组
@AliasFor("basePackages")
String[] value() default {};
// 指定扫描包的位置(同:value 属性)
@AliasFor("value")
String[] basePackages() default {};
// 指定具体的扫描的类
Class<?>[] basePackageClasses() default {};
// bean的名称的⽣成器
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
// 控制符合组件检测条件的类⽂件默认是包扫描下的 **/*.class
String resourcePattern() default "**/*.class";
// 是否开启对@Component,@Repository,@Service,@Controller的类进⾏检测
boolean useDefaultFilters() default true;
// 包含的过滤条件
spring怎么读取jar文件// 1. FilterType.ANNOTATION:按照注解过滤
// 2. FilterType.ASSIGNABLE_TYPE:按照给定的类型
// 3. FilterType.ASPECTJ:使⽤ASPECTJ表达式
// 4. FilterType.REGEX:正则
// 5. FilterType.CUSTOM:⾃定义规则
ComponentScan.Filter[] includeFilters() default {};
// 排除的过滤条件,⽤法和includeFilters⼀样
ComponentScan.Filter[] excludeFilters() default {};
boolean lazyInit() default false;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
FilterType type() default FilterType.ANNOTATION;
@AliasFor("classes")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] classes() default {};
String[] pattern() default {};
}
}
总结⼀下@ComponentScan的常⽤⽅式如下:
通过使⽤value,basePackages属性来指定扫描范围;
⾃定扫描路径下边带有@Controller,@Service,@Repository,@Component注解加⼊Spring容器
通过includeFilters加⼊扫描路径下没有以上注解的类加⼊spring容器
通过excludeFilters过滤出不⽤加⼊spring容器的类
⾃定义增加了@Component注解的注解⽅式
3. Spring Boot 中 @SpringBootApplication
在创建Spring Boot 项⽬之后,在默认的启动类上会被添加@SpringBootApplication注解,这个注解默认帮我们开启⼀些⾃动配置的功能,⽐如:基于Java的Spring配置,组件扫描,特别是⽤于启⽤Spring Boot的⾃动配置功能。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration          // 允许⾃动配置
@ComponentScan(
excludeFilters = {@Filter(      // 定义排除规则
type = FilterType.CUSTOM,        // 采⽤⾃定义的⽅式
classes = {TypeExcludeFilter.class}  // ⾃定义实现逻辑
), @Filter(                // 同上
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
// 为 @EnableAutoConfiguration 添加 exclude 规则
@AliasFor(
annotation = EnableAutoConfiguration.class,
attribute = "exclude"
)
Class<?>[] exclude() default {};
// 为 @EnableAutoConfiguration 添加 excludeName 规则
@AliasFor(
annotation = EnableAutoConfiguration.class,
attribute = "excludeName"
)
String[] excludeName() default {};
// 为 @ComponentScan 添加 basePackages 规则
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
/
/ 为 @ComponentScan 添加 basePackageClasses 规则
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
}
从上⾯的源码部分可以看到,@SpringBootApplication是⼀个组合注解,也就相当于使⽤⼀个@SpringBootApplication可以替代@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan⼏个注解联合使⽤。
注:此注释从SpringBoot 1.2开始提供,这意味着如果你运⾏的是较低的版本,并且如果你需要这些功能,你需要⼿动添加@Configuration,@CompnentScan和@EnableAutoConfiguration。
那么,可能会有这样的问题,我只是使⽤了⼀个@SpringBootApplication注解,但是我如何对@ComponentScan的属性做⾃定义配置呢?
当然,Spring 团队已经很好的解决了这个问题,在@SpringBootApplication注解类中的属性上添加@AliasFor注解,从⽽实现通过对@SpringBootApplication中的属性进⾏⾃定义,达到对对应的注解的属性的⾃定义。
⽐如:
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
这段代码就是实现,通过对@SpringBootApplication的属性scanBasePackages,实现对@ComponentScan中的属性basePackages进⾏⾃定义。
4. 回答开篇问题
先看看项⽬结构,项⽬⼊⼝⽂件在⼦项⽬security-demo中,并且⼊⼝类所在包位置为:package
com.github.jdkong.security。
也就是说,在不做任何配置的情况下,此项⽬只会扫描当前包路径及其⼦路径下的⽂件,并将符合条件的对象注⼊到容器中管理。
再看看配置⽂件所在的包路径位置:package com.github.fig,可见此包路径并不在项⽬扫描的路径范围之内。
这也就导致了,我们定义的配置类,虽然加了@Configuration也不会对我们的项⽬起到作⽤。
可以对项⽬注解进⾏稍微修改,制定扫描包的范围,就可以简单的解决这个问题。如下:
@SpringBootApplication(scanBasePackages="com.github.jdkong")
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class,args);
}
5. 补充说明:@AliasFor
在Spring注解中,经常会发现很多注解的不同属性起着相同的作⽤,⽐如@ComponentScan的value属性和basePackages属性。所以在使⽤的时候就需要做⼀些基本的限制,⽐如value和basePackages的值不能冲突,⽐如任意设置value或者设置basePackages属性的值,都能够通过另⼀个属性来获取值等等。为了统⼀处理这些情况,Spring创建了@AliasFor标签。以上这篇解决Spring Boot 多模块注⼊访问不到jar包中的Bean问题就是⼩编分享给⼤家的全部内容了,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。