Spring提供了一系列以Enable开头的注解,这些注解本质上是激活Spring的某些管理功能。比如,EnableWebMvc。 这个注解引入了MVC框架在Spring 应用中需要用到的所有bean。另外一个注解式EnableAsync, 它让Bean在spring 应用中支持异步功能。
我很好奇这些注解是怎样工作的,并把我的理解写下来。这些注解的工作原理可以理解为SPI的一部分,如果将来实现有变化可以切换。
简单的Enable*注解
我们可以把这些简单的注解理解为为spring 上下文引入一组bean。 我们开始来定义一些这样的注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface EnableSomeBeans {}
并把这个注解应用到spring 配置类上:
@Configuration @EnableSomeBeans public static class SpringConfig {}
如果希望引入一组新的bean, 只需要简单的使用@Import注解,如下:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Import(SomeBeanConfiguration.class) @interface EnableSomeBeans {}
如果被引入的@Configuration定义了Bean, 那么这么bean就会被引入到spring 上下文。
@Configuration class SomeBeanConfiguration { @Bean public String aBean1() { return "aBean1"; } @Bean public String aBean2() { return "aBean2"; } }
完整代码可以从这里下载:https://gist.github.com/bijukunjummen/847456b55ae2340fff65
带Selector的Enable注解
当然,Enable注解可以更加复杂,可以根据所在上下文来激活不同类型的bean。比如:EnableCaching,可以根据类路径上的不同实现来激活对应的缓存。
这样的注解比前面的例子复杂些:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Import(SomeBeanConfigurationSelector.class) public @interface EnableSomeBeansSelector { String criteria() default "default"; }
上面的注解有一个叫criteria的属性,我想根据这个属性来激活不同的bean。这可以通过定义一个@Configuration Selector返回不同的@Configuration来实现。样板代码如下:
mport org.springframework.context.annotation.ImportSelector; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; public class SomeBeanConfigurationSelector implements ImportSelector { @Override public 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 { @Bean public String aBean() { return "Type1"; } } @Configuration class SomeBeanConfigurationDefault { @Bean public String aBean() { return "Default"; } }
所以,如果criteria是detaul, SomeBeanConfigurationDefault被加入,反之,加入SomeBeanConfigurationType1。
原文地址:http://www.java-allandsundry.com/2015/04/spring-enable-annotation-writing-custom.html