@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:

  1. 自定义一个scope注解
@Retention(RetentionPolicy.RUNTIME)
public @interface MyScope {
	String value() default ConfigurableBeanFactory.SCOPE_SINGLETON;
	ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

可以对比下Spring自带的@scope注解

  1. 把自定义的MyScope注解加在我们的组件上
@Component
//注意这里也指定的是SCOPE_PROTOTYPE
@MyScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class CustomScopeAnnotationBean {
}

  1. 那思考我们在创建bean的过程中如何解析我们的MyScope注解呢?

通过scopeResolver属性

@Configuration
@ComponentScan(basePackages = "example.scannable_scoped", scopeResolver = MyScopeMetadataResolver.class)
class ComponentScanWithScopeResolver {
}
  1. 自定义解析类
class MyScopeMetadataResolver extends AnnotationScopeMetadataResolver {

	MyScopeMetadataResolver() {
		this.scopeAnnotationType = MyScope.class;
	}
}

这里只是将父类中的Scope.class换换成了MyScope.class

  1. 测试类
	@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));
	}

单测通过,

看到我们的注解已经生效了

posted @ 2020-10-25 17:22  HeliusKing  阅读(516)  评论(0编辑  收藏  举报