原文地址: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:
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:
02 |
class SomeBeanConfiguration { |
05 |
public String aBean1() { |
10 |
public String aBean2() { |
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"; |
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; |
05 |
public class SomeBeanConfigurationSelector implements ImportSelector { |
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"}; |
16 |
return new String[]{"enableannot.selector.SomeBeanConfigurationType1"}; |
22 |
class SomeBeanConfigurationType1 { |
25 |
public String aBean() { |
32 |
class SomeBeanConfigurationDefault { |
35 |
public String aBean() { |
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.
- 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 ...
- Spring 4 Ehcache Configuration Example with @Cacheable Annotation
http://www.concretepage.com/spring-4/spring-4-ehcache-configuration-example-with-cacheable-annotatio ...
- Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制
Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制 201311.27 代码下载 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t 前言 ...
- Spring整合Hibernate:2、使用Annotation方式进行声明式的事务管理
1.加入DataSourceTransactionManager的命名空间 修改applicationContext.xml文件,增加如下内容: 1 2 3 4 5 6 7 8 9 10 11 12 ...
- 看Spring源码不得不会的@Enable模块驱动实现原理讲解
这篇文章我想和你聊一聊 spring的@Enable模块驱动的实现原理. 在我们平时使用spring的过程中,如果想要加个定时任务的功能,那么就需要加注解@EnableScheduling,如果想使用 ...
- 尚学堂Spring视频教程(四):使用Annotation
之前我们的bean都配置在XML里,并且通过bean的property标签来指定依赖关系,如果项目很大,那岂不是要配置很多这样的property标签?Spring提供了注解的方式来解决这个问题 @Au ...
- Spring(3.2.3) - Beans(8): 基于 Annotation 的配置
除了基于 XML 的配置外,Spring 也支持基于 Annotation 的配置.Spring 提供以下介个 Annotation 来标注 Spring Bean: @Component:标注一个普 ...
- Spring MVC 学习笔记3 - 利用Default Annotation 模式获取请求,使Controller与View对应,并传值。
1. WEB-INF/web.xml 这里定义了获取请求后,执行的第一步.抓取请求. <servlet> <servlet-name>appServlet</servle ...
- Spring使用AspectJ开发AOP:基于Annotation
基于 Annotation 的声明式 在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关的配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维 ...
随机推荐
- a标签点击跳转失效--IE6、7的奇葩bug
一般运用a标签包含img去实现点击图片跳转的功能,这是前端经常要用到的东西. 今天遇到个神奇的bug:如果在img上再包裹一层div,而且div设置了width和height,则图片区域点击时,无任何 ...
- Unity 序列化
Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http://docs ...
- PHP中遍历XML之SimpleXML
简单来讲述一些XML吧,XML是可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言.XML是当今用于传输数据的两大工具之一,另外一个是json. 我们在PHP中使用XML也是用来传输数据, ...
- submit text3常用快捷键
在网上找了一些submit text的快捷键: Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选择需要合并的 ...
- RabbitMq应用一
RabbitMq应用一 RabbitMQ的具体概念,百度百科一下,我这里说一下我的理解,如果有少或者不对的地方,欢迎纠正和补充. 一个项目架构,小的时候,一般都是传统的单一网站系统,或者项目,三层架构 ...
- [转]Patch文件结构详解
N久不来 于是不知道扔在哪儿于是放这里先 如果你觉得碍事的话 帮我扔到合适的版块去.. 导读这是一篇说明文 它介绍了标准冒险岛更新文件(*.patch;*.exe)的格式文章的最后附了一段C#的参考代 ...
- JavaScript基础知识总结(三)
JavaScript语法 七.循环语句 1.while 语法: while (exp) { //statements; } 说明:while (变量<=结束值) { 需执行的代码 } 例子: / ...
- 以向VS 程序打包集成自动写入注册表功能为例,介绍如何实现自由控制安装过程
最近由于项目部署时需要更灵活的控制程序安装的流程以及自定义安装行为,特意研究了一下VS程序打包,把解决办法和大家分享一下. 以VS2010为例: 这是一个已经设置好最基本的Visual Studio ...
- Entity Framework 教程——DBContext
DBContext: 在之前的章节<创建实体数据模型>中,EDM为我们创建了SchoolDBEntities 类,它派生子System.Data.Entity.DbContext这个类,这 ...
- css知多少之绝对定位小记
一.position定位常见属性 对于属性position来说,属性值有static/relative/absolute/fixed/inherit以下只对绝对定位position:absolute详 ...