Spring提供了一系列名称以Enable *开头的注释,这些注释本质上使某些Spring管理的功能可以被激活。 这样的注释的一个很好的例子是EnableWebMvc ,它引入了在基于Spring的应用程序中支持MVC流所需的所有bean。 另一个很好的例子是EnableAsync注释,用于在基于Spring的应用程序中激活bean以支持异步功能。
我对这样的注释如何工作感到好奇,并希望记录下我的理解。 支持这些注释的方式可以视为SPI的一部分,因此,如果将来内部实现发生更改,则可能会中断。
简单的启用*注释
考虑这些自定义注释的一种方法是,它们将一组新bean添加到Spring的应用程序上下文中。 让我们首先定义一个这样的自定义注释:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface EnableSomeBeans {}
并将此注释应用于Spring @Configuration类:
@Configuration
@EnableSomeBeans
public static class SpringConfig {}
因此,现在在应用此批注时引入一组bean就像添加通过@Import批注以这种方式引入的bean组一样简单:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(SomeBeanConfiguration.class)
@interface EnableSomeBeans {}
本质上就是这样,如果此导入的@Configuration类定义了任何bean,则它们现在将成为Application上下文的一部分:
@Configuration
class SomeBeanConfiguration {@Beanpublic String aBean1() {return "aBean1";}@Beanpublic String aBean2() {return "aBean2";}
}
这是一个具有工作样本的要点 。
使用选择器启用*注释
启用注释可能要复杂得多,它们可以根据周围的上下文来激活不同的Bean系列。 这样的注释的一个示例是EnableCaching ,它基于类路径中可用的不同缓存实现来激活配置。
与之前的简单示例相比,编写此类Enable *注释要花费更多的精力。 与之前一样,从一个自定义注释开始:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(SomeBeanConfigurationSelector.class)
public @interface EnableSomeBeansSelector {String criteria() default "default";
}
请注意,在这种情况下,自定义注释具有一个称为标准的示例字段,我要做的是根据此标准激活两组不同的bean。 这可以通过使用@Configuration选择器来实现,该选择器可以根据上下文返回不同的@Configuration文件(在此示例中,criteria字段的值)。 该选择器具有一个简单的签名,这是一个示例实现:
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;public class SomeBeanConfigurationSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {AnnotationAttributes attributes =AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes
(EnableSomeBeansSelector.class.getName(), false));String criteria = attributes.getString("criteria");if (criteria.equals("default")) {return new String[]{"enableannot.selector.SomeBeanConfigurationDefault"};}else {return new String[]{"enableannot.selector.SomeBeanConfigurationType1"};}}
}@Configuration
class SomeBeanConfigurationType1 {@Beanpublic String aBean() {return "Type1";}}@Configuration
class SomeBeanConfigurationDefault {@Beanpublic String aBean() {return "Default";}}
因此,如果条件字段为“默认”,则添加“ SomeBeanConfigurationDefault”中的bean,否则添加“ SomeBeanConfigurationType1”中的bean
- 这是一个具有工作样本的要点 。
结论
我希望这能对Spring如何在内部实现@ Enable *注释有所了解,作为应用程序开发人员,您可能不需要自己创建此类注释,一种更简单的机制是使用@Configuration类和Spring Bean配置文件来组成应用程序。
翻译自: https://www.javacodegeeks.com/2015/04/spring-enable-annotation-writing-a-custom-enable-annotation.html