原文地址: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 配置文件过于臃肿,从而给维 ...
随机推荐
- opencv在图像显示中文
在图像定位和模式识别时,经常需要把结果标注到图片上,标注内容可以是数字字母.矩形框等(opencv支持的)或者是中文汉字(借助freetype). 1.显示数字/矩形框 #include <op ...
- python之路 - 基础1
1.安装windows安装双版本Python2,Python3 下载Python2和Python3https://www.python.org/downloads/ 分别安装两个版本 进入Python ...
- 0.Win8.1,Win10,Windows Server 2012 安装 Net Framework 3.5
后期会在博客首发更新:http://dnt.dkill.net 网站部署之~Windows Server | 本地部署:http://www.cnblogs.com/dunitian/p/482280 ...
- 【SSM框架】Spring + Springmvc + Mybatis 基本框架搭建集成教程
本文将讲解SSM框架的基本搭建集成,并有一个简单demo案例 说明:1.本文暂未使用maven集成,jar包需要手动导入. 2.本文为基础教程,大神切勿见笑. 3.如果对您学习有帮助,欢迎各种转载,注 ...
- Could not create SSL connection through proxy serve-svn
RA layer request failedsvn: Unable to connect to a repository at URL xxxxxx 最后:Could not create SSL ...
- node模块加载层级优化
模块加载痛点 大家也或多或少的了解node模块的加载机制,最为粗浅的表述就是依次从当前目录向上级查询node_modules目录,若发现依赖则加载.但是随着应用规模的加大,目录层级越来越深,若是在某个 ...
- [BootStrap] 富编辑器,基于wysihtml5
在我的周围,已经有很多人在使用BootStrap,但对于任何一个带留言.评论.提问.文章编辑功的网站,编辑器永远是重中之重,显然,早期的编辑器完全没考虑过BootStrap的出现,或皮肤跟网站不匹配, ...
- 微服务与Docker介绍
什么是微服务 微服务应用的一个最大的优点是,它们往往比传统的应用程序更有效地利用计算资源.这是因为它们通过扩展组件来处理功能瓶颈问题.这样一来,开发人员只需要为额外的组件部署计算资源,而不需要部署一个 ...
- 【JS基础】对象
delete 可以删除对象属性及变量 function fun(){ this.name = 'mm'; } var obj = new fun(); console.log(obj.name);// ...
- 如何解决流程开发中SheetRadioButtonList页面取值问题
分享一个常见的取值问题. 应用场景: SheetRadioButtonList控件,点击其中一项执行事件操作.如果是页面加载的情况下,值就无法取到. 具体原因如下: 我给SheetRadioButto ...