Spring5参考指南:组件扫描
组件扫描
上一篇文章我们讲到了annotation-config配置,它主要用于bean内部的属性注入。而bean本身则需要通过配置的方式来定义。如果想使用配置的方式来定义bean,则可以使用component-scan,如下:
<context:component-scan base-package="com.flydean"/>
component-scan会扫描类路径里面的注解注解,包括(@Component, @Repository, @Service,
@Controller, @RestController, @ControllerAdvice, 和@Configuration ), 当然component-scan默认包含了annotation-config,我们可以直接在这些配置bean中使用上篇文章讲到的注解。
@Component
@Component表示该bean是一个组件,@Component是任何Spring管理的组件的通用原型。@Repository、@Service和@Controller是@Component针对更具体的用例(分别在持久性、服务和表示层中)的特殊注解。因此,您可以用@Component注解组件类,但是,通过用@Repository、@Service或@Controller注解它们,您的类更具有语义性。通常更适合在AOP中做进一步的业务逻辑处理。
元注解和组合注解
所谓元注解就是可以用在其他注解中的注解。 像之前提到的@Component就是@Service的元注解。如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
// ....
}
@Component会导致@Service和@Component一样被对待。
当然你也可以组合使用元注解,或者自定义元注解。例如,Spring的@SessionScope注解将作用域名称硬编码为session,但仍允许自定义proxyMode。以下列表显示了sessionScope注解的定义:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @Interface SessionScope {
/**
* Alias for {@link Scope#proxyMode}.
* <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.
*/
@AliasFor(annotation = Scope.class)
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
你可以不定义@SessionScope里面的proxyMode, 如下:
@Service
@SessionScope
public class SessionScopedService {
// ...
}
你也可以重写proxyMode,如下:
@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {
// ...
}
#@ComponentScan和filters
上面我们讲到,要是要使用组件扫描,需要在XML配置context:component-scan, 其实也可以使用注解的形式,如下所示:
@Configuration
@ComponentScan(basePackages = "com.flydean.beans")
public class AppConfig {
}
@ComponentScan可以配置一些filters用来过滤不需要的组件。如下所示:
@Configuration
@ComponentScan(basePackages = "com.flydean.beans",
includeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
excludeFilters = @ComponentScan.Filter(BeanA.class))
public class BeanAConfig {
}
下表是支持的filter类型和例子:
| Filter type | 表达式例子 | 描述 |
|---|---|---|
| annotation(默认) | org.example.SomeAnnotation | type基本的目标组件 |
| assignable | org.example.SomeClass | 目标组件可分配给(扩展或实现)的类(或接口)。 |
| aspectj | org.example…*Service+ | 匹配目标组件的AspectJ类型 |
| regex | org\.example\.Default.* | 匹配目标主键内名的正则表达式 |
| custom | org.example.MyTypeFilter | org.springframework.core.type .TypeFilter的自定义实现 |
组件内部定义Bean元数据
Spring组件还可以为容器提供bean定义元数据。您可以使用用于在@Configuration annotated类中定义bean元数据的相同@Bean注解来实现这一点。以下示例显示了如何执行此操作:
@Component
public class FactoryMethodComponent {
@Bean
@Qualifier("public")
public BeanA publicInstance() {
return new BeanA();
}
public void doWork() {
// Component method implementation omitted
}
}
InjectionPoint
从SpringFramework4.3开始,还可以声明InjectionPoint类型的工厂方法参数,来创建Bean。
注意,这只适用于bean实例的实际创建,而不适用于现有实例的注入。因此,这个特性对于原型范围的bean最有意义。
@Component
public class InjectPointFactoryMethodComponent {
@Bean
@Scope("prototype")
public BeanA prototypeInstance(InjectionPoint injectionPoint) {
return new BeanA("prototypeInstance for " + injectionPoint.getMember());
}
}
常规Spring组件中的@Bean方法的处理方式与Spring@Configuration类中的对应方法不同。不同的是,@Component类没有用cglib来增强以截获方法和字段的调用。cglib代理是调用@Configuration classes中通过@Bean methods内的方法或字段创建对协作对象的bean元数据引用的方法。
你可以将@Bean方法声明为静态方法,允许在不将其包含的配置类创建为实例的情况下调用它们。在定义post-processor bean(例如,BeanFactoryPostProcessor或BeanPostProcessor类型)时,这是特别有意义的,因为这样的bean在容器生命周期的早期就被初始化,应该避免在此时触发配置的其他部分。
由于技术限制,对static @Bean方法的调用永远不会被容器截获,即使是在@Configuration类(如本节前面所述)中也是如此:cglib子类只能重写非静态方法。因此,直接调用另一个@Bean方法相当于标准Java的new方法,导致从工厂方法本身直接返回一个独立的实例。
要注意: @Configuration类中的常规@Bean方法必须是可重写的,也就是说,它们不能声明为私有或最终的。
为自动检测组件命名
默认情况下,可以提供value属性给@Component、@Repository、@Service和@Controller),从而为Bean命名。
如果这样的注解不包含value,则默认bean名称生成器将返回小写的非限定类名。例如,如果检测到以下组件类,则名称为myMovieLister和movieFinderImpl:
@Service("myMovieLister")
public class SimpleMovieLister {
// ...
}
@Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
如果您不想依赖默认的bean命名策略,可以提供一个自定义的bean命名策略。首先,实现BeanNameGenerator接口,并确保包含一个默认的无参数构造函数。然后,在配置扫描器时提供完全限定的类名,如下面的示例注解和bean定义所示:
public class MyNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return null;
}
}
@Configuration
@ComponentScan(basePackages = "com.flydean", nameGenerator = MyNameGenerator.class)
public class BeanNameConfig {
}
为自动检测的组件提供作用域
与一般的Spring管理组件一样,自动检测组件的默认和最常见的作用域是singleton。但是,有时您需要一个可以由@Scope注解指定的不同范围。可以在注解中提供作用域的名称,如下示例所示:
@Scope("prototype")
@Component("beanA")
public class BeanA {
public BeanA(){
}
public BeanA(String name){
}
}
自定义范围解析
要为范围解析提供自定义策略,而不是依赖基于注解的方法,可以实现ScopeMetadataResolver接口。如下所示:
public class MyScopeResolver implements ScopeMetadataResolver {
@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
return null;
}
}
@Configuration
@ComponentScan(basePackages = "com.flydean", scopeResolver = MyScopeResolver.class)
public class BeanScopeResolverConfig {
}
scoped-proxy
当使用某些非单例作用域时,可能需要为作用域对象生成代理。为此,组件扫描元素上可以有一个scoped-proxy 属性。三个可能的值是:no、interfaces和targetClass。例如,以下配置将生成标准JDK动态代理:
@Configuration
@ComponentScan(basePackages = "com.flydean", scopedProxy = ScopedProxyMode.INTERFACES)
public class ScopedProxyConfig {
}
生成候选组件的索引
虽然类路径扫描速度非常快,但是可以通过在编译时创建一个静态候选列表来提高大型应用程序的启动性能。
要生成索引,需要每个模块添加一个附加依赖项,该模块包含作为组件扫描指令目标的组件。下面的示例说明如何使用Maven:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<version>5.1.8.RELEASE</version>
<optional>true</optional>
</dependency>
</dependencies>
这个过程生成一个包含在JAR文件中的META-INF/spring.components文件。
当在类路径上找到META-INF/Spring.components时,索引将自动启用。如果某个索引部分可用于某些库(或用例),但无法为整个应用程序生成,则可以通过将spring.index.ignore设置为true(作为系统属性或类路径根目录下的spring.properties文件)来回滚到常规类路径安排(就像根本没有索引一样)。
本节的例子可以参考 component-scan.
更多教程请参考flydean的博客
Spring5参考指南:组件扫描的更多相关文章
- Spring5参考指南:IOC容器
文章目录 为什么使用Spring5 什么是IOC容器 配置元数据 实例化容器 XML嵌套 groovy bean定义DSL 使用容器 最近在翻译Spring Framework Documentati ...
- Spring5参考指南:Bean的创建
文章目录 Spring容器中的Bean Bean的命名 Bean的实例化 Spring容器中的Bean Bean在Spring中就是一个业务组件,我们通过创建各种Bean来完成最终的业务逻辑功能. 在 ...
- Spring5参考指南:AspectJ注解
文章目录 什么是AspectJ注解 启用AOP 定义Aspect 定义Pointcut 切入点指示符(PCD) 切入点组合 Advice 访问JoinPoint Advice参数 Advice参数和泛 ...
- Spring5参考指南: SpEL
文章目录 Bean定义中的使用 求值 支持的功能 函数 Bean引用 If-Then-Else Elvis Safe Navigation 运算符 集合选择 集合投影 表达式模板化 SpEL的全称叫做 ...
- Spring5参考指南: Resources
文章目录 内置Resource实现 ResourceLoader ResourceLoaderAware 资源作为依赖 构造ClassPathXmlApplicationContext-快捷方式 资源 ...
- Spring5参考指南:事件Event
文章目录 基于继承的Event 基于注解的Event 异步侦听器 Spring提供了很方便的事件的处理机制,包括事件类ApplicationEvent和事件监听类ApplicationListener ...
- Spring5参考指南:JSR 330标准注解
文章目录 @Inject 和 @Named @Named 和 @ManagedBean 之前的文章我们有讲过,从Spring3.0之后,除了Spring自带的注解,我们也可以使用JSR330的标准注解 ...
- Spring5参考指南:基于注解的容器配置
文章目录 @Required @Autowired @primary @Qualifier 泛型 @Resource @PostConstruct和@PreDestroy Spring的容器配置可以有 ...
- Spring5参考指南:容器扩展
文章目录 BeanPostProcessor自定义bean BeanFactoryPostProcessor自定义配置元数据 使用FactoryBean自定义实例化逻辑 Spring提供了一系列的接口 ...
随机推荐
- Python第十三章-网络编程
网络编程 一.网络编程基础 python 的网络编程模块主要支持两种Internet协议: TCP 和 UDP. 1.1通信协议 通信协议也叫网络传输协议或简称为传送协议(Communications ...
- Vertica的这些事(十三)——Vertica备份元数据信息
---备份资源池 SELECT 'CREATE RESOURCE POOL ' || name || CASE WHEN memorysize IS NULL THEN ' ' ELSE ' MEMO ...
- 总结一下python的学习路线
1.安装pycharm community编辑器和python 3.7.2解释器的博客链接参考:https://blog.csdn.net/fangye945a/article/details/878 ...
- Vue设置路由跳转的两种方法: <router-link :to="..."> 和router.push(...)
一.<router-link :to="..."> to里的值可以是一个字符串路径,或者一个描述地址的对象.例如: // 字符串 <router-link to= ...
- CF1292C Xenon's Attack on the Gangs
题目链接:https://codeforces.com/problemset/problem/1292/C 题意 在一颗有n个节点的树上,给每个边赋值,所有的值都在\([0,n-2]\)内并且不重复, ...
- 数据挖掘-K-近邻算法
数据挖掘-K-近邻算法 目录 数据挖掘-K-近邻算法 1. K-近邻算法概述 1.1 K-近邻算法介绍 1.1.1 KNN算法作用 1.1.2 KNN 算法思想 1.1.3 KNN算法特点 1.2 K ...
- .NET Core项目部署到Linux(Centos7)(七)启动和停止.NET Core项目
目录 1.前言 2.环境和软件的准备 3.创建.NET Core API项目 4.VMware Workstation虚拟机及Centos 7安装 5.Centos 7安装.NET Core环境 6. ...
- Spring(四):使用注解开发
本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出一遍就懂!b站搜索狂神说或点击下面链接 https://space.bilibili.com/95256449?spm_id_from=33 ...
- 关于TD信息树自己的体验和建议
自己选择的是17级学长13组的TD消息树,通过对这个软件的使用,感觉整体上还是很好的,他的主要功能就相当于把微信的朋友圈还有qq的好友动态等功能集合到了一起.这个软件整体就相当于一个空间,可以加好友互 ...
- websocket聊天室
目录 websocket方法总结 群聊功能 基于websocket聊天室(版本一) websocket方法总结 # 后端 3个 class ChatConsumer(WebsocketConsumer ...