@ComponentScan的scopeResolver属性详解
@ComponentScan的scopeResolver属性详解
一、源码说明
/**
* The {@link ScopeMetadataResolver} to be used for resolving the scope of detected components.
*/
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
根据注释,我们知道这是一个用来解析bean的scope的属性,
通俗一点来说,Spring中提供了@Scope
注解,用来定义bean的单例还是多例,默认是单例。
Spring官方文档对于这个属性有一段说明:
Like the pre-built annotations for those scopes, you may also compose your own scoping annotations using Spring’s meta-annotation approach: e.g. a custom annotation meta-annotated with @Scope("prototype"), possibly also declaring a custom scoped-proxy mode.
就是也许我们有自定义的Scope,这时我们就需要在scopeResolver属性上指明我们自定义的解析类。
二、举例
To provide a custom strategy for scope resolution rather than relying on the annotation-based approach, implement the
ScopeMetadataResolver
interface, and be sure to include a default no-arg constructor. Then, provide the fully-qualified class name when configuring the scanner:
- 自定义一个scope注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyScope {
String value() default ConfigurableBeanFactory.SCOPE_SINGLETON;
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
可以对比下Spring自带的@scope
注解
- 把自定义的MyScope注解加在我们的组件上
@Component
//注意这里也指定的是SCOPE_PROTOTYPE
@MyScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class CustomScopeAnnotationBean {
}
- 那思考我们在创建bean的过程中如何解析我们的MyScope注解呢?
通过scopeResolver
属性
@Configuration
@ComponentScan(basePackages = "example.scannable_scoped", scopeResolver = MyScopeMetadataResolver.class)
class ComponentScanWithScopeResolver {
}
- 自定义解析类
class MyScopeMetadataResolver extends AnnotationScopeMetadataResolver {
MyScopeMetadataResolver() {
this.scopeAnnotationType = MyScope.class;
}
}
这里只是将父类中的Scope.class换换成了MyScope.class
- 测试类
@Test
public void withScopeResolver() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ComponentScanWithScopeResolver.class);
// custom scope annotation makes the bean prototype scoped. subsequent calls
// to getBean should return distinct instances.
assertThat(ctx.getBean(CustomScopeAnnotationBean.class)).isNotSameAs(ctx.getBean(CustomScopeAnnotationBean.class));
}
单测通过,
看到我们的注解已经生效了
你所看得到的天才不过是在你看不到的时候还在努力罢了!