通过注解实现bean在容器中的注册。
要使用这方面的注解,首先得先开启包扫描,用于指定哪个包进行自动检测。
XML配置:
<context:component-scan base-package="org.example"/>基于Java的容器配置:
@Configuration @ComponentScan(basePackages = "org.example") public class AppConfig { // ... }在base-package属性中你可以用逗号、空格和分号分隔开多个包。
<context:component-scan/>标签隐式的启用了<context:annotation-config />功能,所以可以省略。
当然,你也可以通过**<context:component-scan annotation-config=“false”/>**来禁用AutowiredAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor。
通过@Components注解实现bean注册。如果你不指定其限定符属性,默认情况下,采用类名首字母小写作为限定符,指定限定符则用@Qualifier注解。
@Components//或@Service public class UserServie {//默认限定符:userServie // ... } @Components @Qualifier("userServie")//指定限定符 public class UserServie { // ... }如果,你并不希望采用Spring默认组件命名策略,可以自定义组件命名策略,通过实现BeanNameGenerator接口并有一个默认的无参构造方法,然后在包扫描中配置即可。
XML配置:
<context:component-scan name-generator="org.example.MyNameGenerator" />基于Java的容器配置:
@Configuration @ComponentScan(nameGenerator = MyNameGenerator.class) public class AppConfig { // ... }在Spring Framework 5.2.3中,通过使用FullyQualifiedAnnotationBeanNameGenerator类可以实现完全限定类名的组件命名策略。
此外,在web开发中,你还可以用@Repository, @Service, and @Controller来注册Bean,它们用于更具体的组件(分别为持久层、业务层和表示层)的专用化。通过查看注解源码可以发现它们都拥有@Components元注解。
当然,你可以通过组合一系列注解实现复合注解,如SpringMVC中@RestController就实现了@Controller和@ResponseBody的复合。
通过在包扫描中配置includeFilters、excludeFilters你可以在扫描中加入或排除指定组件,其中type属性用于指定过滤器类型,expression属性指定表达式。
XML配置:
<context:component-scan base-package="..." > <context:exclude-filter type=".." expression=".."/> <context:include-filter type=".." expression=".."/> </context:component-scan>基于Java的注解配置:
@Configuration @ComponentScan( includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"), excludeFilters = @Filter(Repository.class)) public class AppConfig { ... }过滤器类型如下表:
类型表达式示例描述annotation(默认)org.example.SomeAnnotation根据注解进行过滤assignableorg.example.SomeClass根据类型(或接口)进行过滤aspectjorg.example…*Service+根据AspectJ类型表达式进行过滤regexorg.example.Default.*根据正则表达式进行过滤customorg.example.MyTypeFilter根据定制的过滤器进行过滤(定制过滤器要实现TypeFilter接口)在使用这些过滤器的时候,你还可以在包扫描中配置 useDefaultFilters=false(或XML配置的use-default-filters=“false”)来实现禁止默认过滤器,这将有效的禁止默认注解(如@Component、@Configuration)的自动检测。
通过@Scope注解可以实现配置作用域。该注解仅在具体的Bean类或@Bean方法上使用,与XML配置相反,它并没有作用域继承的概念。
@Scope("prototype") @Repository public class ExampleImpl implements Example { // ... }同样的,也可通过@scopedProxy 注解配置作用域代理。
XML配置:
<beans> <context:component-scan base-package="org.example" scoped-proxy="interfaces"/> </beans>注解配置:
@Configuration @ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)//或ScopedProxyMode.TARGET_CLASS public class AppConfig { // ... }你可以使用JSR-330标准的注解代替一些Spring注解,首先得加入依赖关系。
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> @Inject代替@Autowired与@Autowired一样,可以通过@Inject对字段、方法和构造参数进行注入(@Inject无required属性)。甚至可以使用@Nullable允许为空。
@Named代替@Qualifier若在使用@Inject时需要进一步对限定符进行匹配,可以使用@Named
@Named/@ManagedBean代替@Component可以使用@Named或@ManagedBean(两者不可组合)标识组件,并且依然可以被@ComponentScan扫描到
在大型应用中,你可以通过创建索引来提高包扫描效率。
首先你需要引入相关依赖。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-indexer</artifactId> <version>5.3.0-SNAPSHOT</version> <optional>true</optional> </dependency>之后,在你需要索引的Bean上添加@Indexed即可。
该依赖会在构建时创建一个在jar包中的META-INF/spring.components文件,当Spring找到此路径文件时,会自动开启索引。
需要注意的是,在多模块开发时,如果A模块开启索引,B模块不开启索引,则会出B模块bean无法被找到的错误。