原文地址: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 配置文件过于臃肿,从而给维 ...
随机推荐
- 微信小程序开发心得
微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...
- iPhone Anywehre虚拟定位提示“后台服务未启动,请重新安装应用后使用”的解决方法
问题描述: iPhone越狱了,之后在Cydia中安装Anywhere虚拟定位,但是打开app提示:后台服务未启动,请重新安装应用后使用. 程序无法正常使用... 解决方法: 打开Cydia-已安装, ...
- 微信小程序体验(2):驴妈妈景区门票即买即游
驴妈妈因为出色的运营能力,被腾讯选为首批小程序内测单位.驴妈妈的技术开发团队在很短的时间内完成了开发任务,并积极参与到张小龙团队的内测问题反馈.驴妈妈认为,移动互联网时代,微信是巨大的流量入口,也是旅 ...
- 高频交易算法研发心得--MACD指标算法及应用
凤鸾宝帐景非常,尽是泥金巧样妆. 曲曲远山飞翠色:翩翩舞袖映霞裳. 梨花带雨争娇艳:芍药笼烟骋媚妆. 但得妖娆能举动,取回长乐侍君王. [摘自<封神演义>纣王在女娲宫上香时题的诗] 一首定 ...
- git克隆项目到本地&&全局安装依赖项目&&安装依赖包&&启动服务
一.安装本地开发环境 1.安装本项目 在需要保存到本地的项目的文件夹,进入到文件夹里点击右键,bash here,出现下图: 2.安装依赖项目 3.安装依赖包(进入到命令行) # 安装依赖包 $ ...
- 开发者的利器:Docker 理解与使用
困扰写代码的机器难免会被我们安装上各种各样的开发工具.语言运行环境和引用库等一大堆的东西,长久以来不仅机器乱七八糟,而且有些相同的软件还有可能会安装不同的版本,这样又会导致一个项目正常运行了,却不小心 ...
- JAVA构造时成员初始化的陷阱
让我们先来看两个类:Base和Derived类.注意其中的whenAmISet成员变量,和方法preProcess(). 情景1:(子类无构造方法) class Base { Base() { pre ...
- jquery中的$(document).ready(function() {});
当文档载入时执行function函数里的代码, 这部分代码主要声明,页面加载后 "监听事件" 的方法.例如: $(document).ready( $("a") ...
- 【Java每日一题】20170106
20170105问题解析请点击今日问题下方的"[Java每日一题]20170106"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- Springboot搭建web项目
最近因为项目需要接触了springboot,然后被其快速零配置的特点惊呆了.关于springboot相关的介绍我就不赘述了,大家自行百度google. 一.pom配置 首先,建立一个maven项目,修 ...