SpringBoot中神奇的@Enable*注解?
在springboot开发过程,我们经常会遇到@enable开始的好多注解,比如@enableeurekaserver、@enableasync、@enablescheduling等,今天我们就来分析下这些注解到底是如何工作的?
本文目录
一、@enable*实现的原理二、@import注解的用法3. 动态注册bean
一、@enable*实现的原理
通过这些@enable*注解的源码可以看出,所有@enable*注解里面都有一个@import注解,而@import是用来导入配置类的,所以@enable*自动开启的实现原理其实就是导入了一些自动配置的bean。
二、@import注解的用法
@import注解允许导入@configuration类,importselector和importbeandefinitionregistrar的实现类,等同于正常的组件类。
有以下三种使用方式
1. 直接导入配置类
@enableeurekaserver使用了这种方式,注解源码如下:
@target({elementtype.type})
@retention(retentionpolicy.runtime)
@documented
@import({eurekaservermarkerconfiguration.class})
public @interface enableeurekaserver {
}
可以看到@enableeurekaserver注解直接导入了配置类eurekaservermarkerconfiguration,而这个配置类中向spring容器中注册了一个eurekaservermarkerconfiguration的bean。
eurekaservermarkerconfiguration的源码如下:
@configuration
public class eurekaservermarkerconfiguration {
public eurekaservermarkerconfiguration() {
}
@bean
public eurekaservermarkerconfiguration.marker eurekaservermarkerbean() {
return new eurekaservermarkerconfiguration.marker();
}
class marker {
marker() {
}
}
}
2. 依据条件选择配置类
@enableasync使用了这种方式,注解源码如下:
@target(elementtype.type)
@retention(retentionpolicy.runtime)
@documented
@import(asyncconfigurationselector.class)
public @interface enableasync {
class<? extends annotation> annotation() default annotation.class;
boolean proxytargetclass() default false;
advicemode mode() default advicemode.proxy;
int order() default ordered.lowest_precedence;
}
enableasync注解中导入了asyncconfigurationselector,asyncconfigurationselector通过条件来选择需要导入的配置类,继承advicemodeimportselector又实现了importselector接口,接口重写selectimports方法进行事先条件判断proxy或者aspectj选择不同的配置类。
asyncconfigurationselector源码如下:
public class asyncconfigurationselector extends advicemodeimportselector<enableasync> {
private static final string async_execution_aspect_configuration_class_name =
"org.springframework.scheduling.aspectj.aspectjasyncconfiguration";
/**
* returns {@link proxyasyncconfiguration} or {@code aspectjasyncconfiguration}
* for {@code proxy} and {@code aspectj} values of {@link enableasync#mode()},
* respectively.
*/
@override
@nullable
public string[] selectimports(advicemode advicemode) {
switch (advicemode) {
case proxy:
return new string[] {proxyasyncconfiguration.class.getname()};
case aspectj:
return new string[] {async_execution_aspect_configuration_class_name};
default:
return null;
}
}
}
3. 动态注册bean
@enableaspectjautoproxy使用了这种方式,注解源码如下:
@target(elementtype.type)
@retention(retentionpolicy.runtime)
@documented
@import(aspectjautoproxyregistrar.class)
public @interface enableaspectjautoproxy {
boolean proxytargetclass() default false;
boolean exposeproxy() default false;
}
enableaspectjautoproxy注解中导入了aspectjautoproxyregistrar,aspectjautoproxyregistrar实现了importbeandefinitionregistrar接口,在运行时把bean注册到spring容器中。
aspectjautoproxyregistrar的源码如下:
class aspectjautoproxyregistrar implements importbeandefinitionregistrar {
/**
* register, escalate, and configure the aspectj auto proxy creator based on the value
* of the @{@link enableaspectjautoproxy#proxytargetclass()} attribute on the importing
* {@code @configuration} class.
*/
@override
public void registerbeandefinitions(
annotationmetadata importingclassmetadata, beandefinitionregistry registry) {
aopconfigutils.registeraspectjannotationautoproxycreatorifnecessary(registry);
annotationattributes enableaspectjautoproxy =
annotationconfigutils.attributesfor(importingclassmetadata, enableaspectjautoproxy.class);
if (enableaspectjautoproxy != null) {
if (enableaspectjautoproxy.getboolean("proxytargetclass")) {
aopconfigutils.forceautoproxycreatortouseclassproxying(registry);
}
if (enableaspectjautoproxy.getboolean("exposeproxy")) {
aopconfigutils.forceautoproxycreatortoexposeproxy(registry);
}
}
}
}
推荐阅读
1.java中integer.parseint和integer.valueof,你还傻傻分不清吗?
2.springcloud系列-整合hystrix的两种方式)
3.springcloud系列-利用feign实现声明式服务调用)
4.手把手带你利用ribbon实现客户端的负载均》
5.springcloud搭建注册中心与服务注册
java碎碎念公众号限时领取免费java相关资料,涵盖了java、redis、mongodb、mysql、zookeeper、spring cloud、dubbo/kafka、hadoop、hbase、flink等高并发分布式、大数据、机器学习等技术。
关注下方公众号即可免费领取:
下一篇: 常用数组、字符串的方法(详解)