原文地址:https://www.javacodegeeks.com/2015/04/spring-enable-annotation-writing-a-custom-enable-annotation.html

Spring provides a range of annotations with names starting with Enable*, these annotations in essence enable certain Spring managed features to be activated. One good example of such an annotation is EnableWebMvcwhich brings in all the beans needed to support a MVC flow in Spring based applications. Another good example is the EnableAsync annotation to activate beans to support async functionality in Spring based applications.

I was curious about how such annotations work and wanted to document my understanding. The way these annotations are supported can be considered part of the SPI and so may break if the internal implementation changes in future.

Simple Enable* Annotations

One way to think about these custom annotations is that they add a set of new beans into the Spring’s application context. Let us start by defining one such custom annotation:

1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.TYPE)
3 @interface EnableSomeBeans {}

and apply this annotation on a Spring @Configuration class:

1 @Configuration
2 @EnableSomeBeans
3 public static class SpringConfig {}

So now to bring in a set of beans when this annotation is applied is as simple as adding the set of beans to bring in using @Import annotation this way:

1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.TYPE)
3 @Import(SomeBeanConfiguration.class)
4 @interface EnableSomeBeans {}

That is essentially it, if this imported @Configuration class defines any beans, they would now be part of the Application context:

01 @Configuration
02 class SomeBeanConfiguration {
03  
04     @Bean
05     public String aBean1() {
06         return "aBean1";
07     }
08  
09     @Bean
10     public String aBean2() {
11         return "aBean2";
12     }
13 }

Here is a gist with a working sample.

Enable* Annotations with Selectors

Enable annotations can be far more complex though, they can activate a different family of beans based on the context around them. An example of such an annotation is EnableCaching which activates configuration based on different caching implementations available in the classpath.

Writing such Enable* annotations is a little more involved than the simpler example earlier. As before start with a custom annotation:

1 @Retention(RetentionPolicy.RUNTIME)
2 @Target(ElementType.TYPE)
3 @Import(SomeBeanConfigurationSelector.class)
4 public @interface EnableSomeBeansSelector {
5     String criteria() default "default";
6 }

Note that in this case the custom annotation has a sample field called criteria, what I want to do is to activate two different set of beans based on this criteria. This can be achieved using a @Configuration selector which can return different @Configuration file based on the context(in this instance the value of the criteria field). This selector has a simple signature and this is a sample implementation:

01 import org.springframework.context.annotation.ImportSelector;
02 import org.springframework.core.annotation.AnnotationAttributes;
03 import org.springframework.core.type.AnnotationMetadata;
04  
05 public class SomeBeanConfigurationSelector implements ImportSelector {
06     @Override
07     public String[] selectImports(AnnotationMetadata importingClassMetadata) {
08         AnnotationAttributes attributes =
09                 AnnotationAttributes.fromMap(
10                         importingClassMetadata.getAnnotationAttributes
11 (EnableSomeBeansSelector.class.getName(), false));
12         String criteria = attributes.getString("criteria");
13         if (criteria.equals("default")) {
14             return new String[]{"enableannot.selector.SomeBeanConfigurationDefault"};
15         }else {
16             return new String[]{"enableannot.selector.SomeBeanConfigurationType1"};
17         }
18     }
19 }
20  
21 @Configuration
22 class SomeBeanConfigurationType1 {
23  
24     @Bean
25     public String aBean() {
26         return "Type1";
27     }
28  
29 }
30  
31 @Configuration
32 class SomeBeanConfigurationDefault {
33  
34     @Bean
35     public String aBean() {
36         return "Default";
37     }
38  
39 }

So if the criteria field is “default”, the beans in “SomeBeanConfigurationDefault” gets added in, else the one in “SomeBeanConfigurationType1”

  • Here is a gist with a working sample.

Conclusion

I hope this gives an appreciation for how Spring internally implements the @Enable* annotations, as an application developer you may not need to create such annotations yourself, a simpler mechanism will be to use @Configuration classes and Spring bean profiles to compose applications.

Spring Enable annotation – writing a custom Enable annotation的更多相关文章

  1. Define custom @Required-style annotation in Spring

    The @Required annotation is used to make sure a particular property has been set. If you are migrate ...

  2. Spring 4 Ehcache Configuration Example with @Cacheable Annotation

    http://www.concretepage.com/spring-4/spring-4-ehcache-configuration-example-with-cacheable-annotatio ...

  3. Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制

    Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制 201311.27 代码下载 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t 前言 ...

  4. Spring整合Hibernate:2、使用Annotation方式进行声明式的事务管理

    1.加入DataSourceTransactionManager的命名空间 修改applicationContext.xml文件,增加如下内容: 1 2 3 4 5 6 7 8 9 10 11 12 ...

  5. 看Spring源码不得不会的@Enable模块驱动实现原理讲解

    这篇文章我想和你聊一聊 spring的@Enable模块驱动的实现原理. 在我们平时使用spring的过程中,如果想要加个定时任务的功能,那么就需要加注解@EnableScheduling,如果想使用 ...

  6. 尚学堂Spring视频教程(四):使用Annotation

    之前我们的bean都配置在XML里,并且通过bean的property标签来指定依赖关系,如果项目很大,那岂不是要配置很多这样的property标签?Spring提供了注解的方式来解决这个问题 @Au ...

  7. Spring(3.2.3) - Beans(8): 基于 Annotation 的配置

    除了基于 XML 的配置外,Spring 也支持基于 Annotation 的配置.Spring 提供以下介个 Annotation 来标注 Spring Bean: @Component:标注一个普 ...

  8. Spring MVC 学习笔记3 - 利用Default Annotation 模式获取请求,使Controller与View对应,并传值。

    1. WEB-INF/web.xml 这里定义了获取请求后,执行的第一步.抓取请求. <servlet> <servlet-name>appServlet</servle ...

  9. Spring使用AspectJ开发AOP:基于Annotation

    基于 Annotation 的声明式 在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关的配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维 ...

随机推荐

  1. SQLSERVER将一个文件组的数据移动到另一个文件组

    SQLSERVER将一个文件组的数据移动到另一个文件组 有经验的大侠可以直接忽视这篇文章~ 这个问题有经验的人都知道怎麽做,因为我们公司的数据量不大没有这个需求,也不知道怎麽做实验 今天求助了QQ群里 ...

  2. nodejs进阶(5)—接收请求参数

    1. get请求参数接收 我们简单举一个需要接收参数的例子 如果有个查找功能,查找关键词需要从url里接收,http://localhost:8000/search?keyword=地球.通过前面的进 ...

  3. HTML块级元素

    前面的话   在HTML5出现之前,人们一般把元素分为块级.内联和内联块元素.本文将详细介绍HTML块级元素 h   标题(Heading)元素有六个不同的级别,<h1>是最高级的,而&l ...

  4. JS与APP原生控件交互

    "热更新"."热部署"相信对于混合式开发的童鞋一定不陌生,那么APP怎么避免每次升级都要在APP应用商店发布呢?这里就用到了混合式开发的概念,对于电商网站尤其显 ...

  5. 学习ASP.NET Core,怎能不了解请求处理管道[1]: 中间件究竟是个什么东西?

    ASP.NET Core管道虽然在结构组成上显得非常简单,但是在具体实现上却涉及到太多的对象,所以我们在 "通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流 ...

  6. C#为IE编写BHO插件心得

    啥是BHO,其实大家都用过,没听过只是没在意而已,来张图你就知道是什么了 是不是很熟悉,就是这么个玩意~~ 先说说我要用来干嘛~我们有个库,里面数据很全面,但是某个部门需要在第三方的B/S系统录入某些 ...

  7. 免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)

    前面介绍了六种.NET组件,其中有一种组件是写文件的压缩和解压,现在介绍另一种文件的解压缩组件SharpZipLib.在这个组件介绍系列中,只为简单的介绍组件的背景和简单的应用,读者在阅读时可以结合官 ...

  8. WPF中Grid实现网格,表格样式通用类

    /// <summary> /// 给Grid添加边框线 /// </summary> /// <param name="grid"></ ...

  9. RabbitMQ + PHP (三)案例演示

    今天用一个简单的案例来实现 RabbitMQ + PHP 这个消息队列的运行机制. 主要分为两个部分: 第一:发送者(publisher) 第二:消费者(consumer) (一)生产者 (创建一个r ...

  10. npm源切换

    版权声明:欢迎转载,请附加转载来源:一路博客(http://www.16boke.com)   目录(?)[+] 安装 使用 列出可选的源 切换 增加源 删除源 测试速度 许可 项目主页   我们介绍 ...