当前位置: 移动技术网 > IT编程>开发语言>Java > SpringBoot中神奇的@Enable*注解?

SpringBoot中神奇的@Enable*注解?

2019年10月24日  | 移动技术网IT编程  | 我要评论

在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、redis、mongodb、mysql、zookeeper、spring cloud、dubbo/kafka、hadoop、hbase、flink等高并发分布式、大数据、机器学习等技术。
关注下方公众号即可免费领取:

java碎碎念公众号java碎碎念公众号

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网