精华内容
下载资源
问答
  • 在我们日常开发中,经常使用Enable注解来开启某些功能。例如 EnableDiscoveryClient EnableFeignClients @EnableAuthorizationServer .... 我们发现这些注解都是用来开启某些功能的,其实如果...

    在我们日常开发中,经常使用Enable注解来开启某些功能。例如

    1. EnableDiscoveryClient
    2. EnableFeignClients
    3. @EnableAuthorizationServer
    4. ....

    我们发现这些注解都是用来开启某些功能的,其实如果我们换句话来说可能更好理解,就是用来加载某些配置的。

    那么我们来自定义一个Enable注解,首先我们需要对注解有一定的了解,下面是我摘抄的网上的一段说明。

    01) @interface

    使用 @interface 定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation。

    定义 Annotation 时,@interface 是必须的。

    注意:它和我们通常的 implemented 实现接口的方法不同。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注解后,该注解不能继承其他的注解或接口。

    (02) @Documented

    类和方法的 Annotation 在缺省情况下是不出现在 javadoc 中的。如果使用 @Documented 修饰该 Annotation,则表示它可以出现在 javadoc 中。

    定义 Annotation 时,@Documented 可有可无;若没有定义,则 Annotation 不会出现在 javadoc 中。

    (03) @Target(ElementType.TYPE)

    前面我们说过,ElementType 是 Annotation 的类型属性。而 @Target 的作用,就是来指定 Annotation 的类型属性。

    @Target(ElementType.TYPE) 的意思就是指定该 Annotation 的类型是 ElementType.TYPE。这就意味着,MyAnnotation1 是来修饰"类、接口(包括注释类型)或枚举声明"的注解。

    定义 Annotation 时,@Target 可有可无。若有 @Target,则该 Annotation 只能用于它所指定的地方;若没有 @Target,则该 Annotation 可以用于任何地方。

    (04) @Retention(RetentionPolicy.RUNTIME)

    前面我们说过,RetentionPolicy 是 Annotation 的策略属性,而 @Retention 的作用,就是指定 Annotation 的策略属性。

    @Retention(RetentionPolicy.RUNTIME) 的意思就是指定该 Annotation 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将该 Annotation 信息保留在 .class 文件中,并且能被虚拟机读取。

    定义 Annotation 时,@Retention 可有可无。若没有 @Retention,则默认是 RetentionPolicy.CLASS。

    下面我们说了怎么自定义一个Enable注解,其实Enable的方式有很多种。

    我们先介绍最简单的一种,直接引入:

    /**
     * 开启天润外呼
     * @author clark
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Import(TRCallConfig.class)
    public @interface EnableTRCall {
    }

    引入配置类

    /**
     * 天润外呼配置类
     * @author clark
     */
    @EnableConfigurationProperties({ TRCallProperties.class})
    public class TRCallConfig {
    
        @Autowired
        private TRCallProperties trCallProperties;
    
        /**
         * 实例化天润外呼业务
         * @return
         */
        @Bean("trCallService")
        CallService trCallService(){
            TRCallServiceImpl trCallService = new TRCallServiceImpl();
            trCallService.setTrCallProperties(trCallProperties);
            return trCallService;
        }
    }

    那么这样我们就实现了一个自定义的Eable注解了,当然这是比较简单的。

    下面我们来说下第二种,根据参数加载不同的配置类的方法。

    /**
     * 全局开启外呼注解:与单个开启等价
     * @author clark
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Import(CallConfigurationSelector.class)
    public @interface EnableCall {
        /**
         * 开启类型
         * @return
         */
        String[] type();
    
    }
    /**
     * 配置加载
     * @author clark
     */
    public class CallConfigurationSelector  implements ImportSelector{
    
        /**
         * 解析type参数,动态加载配置类
         * @param annotationMetadata
         * @return
         */
        @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            //获取注解的属性集合
            AnnotationAttributes attributes =
                    AnnotationAttributes.fromMap(
                            annotationMetadata.getAnnotationAttributes(EnableCall.class.getName(), false));
            //设置type
            String[] types = attributes.getStringArray("type");
            if(types==null||types.length==0){
                throw new IllegalStateException("type is required");
            }
            List<String> results = new ArrayList<>();
            //处理类型
            for(String type : types) {
                CallType callType = CallType.valueOf(type);
                switch (callType) {
                    case CDR:
                        results.add(CDRCallConfig.class.getName());
                        break;
                    case TKY:
                        results.add(TKYCallConfig.class.getName());
                        break;
                    case TR:
                        results.add(TRCallConfig.class.getName());
                        break;
                    case ZC:
                        results.add(ZCCallConfig.class.getName());
                        break;
                    default:
                        throw new IllegalStateException("no type is matching");
                }
            }
            return results.toArray(new String[results.size()]);
        }
    
    }

    对于Import能引入的类型,我们可以参考源码进行查看。

    展开全文
  • springboot 自定义Enable* 注解

    千次阅读 2018-10-18 10:00:53
    1.定义一个注解类 EnableScanner package com.boot.condition.bootcondition.simple; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure....

    项目结构:

    1.定义一个注解类 EnableScanner

    package com.boot.condition.bootcondition.simple;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    /**
     * 〈一句话功能简述〉<br> 
     * 〈扫描包〉
     *
     * @author 26918
     * @create 2018/10/17
     * @since 1.0.0
     */
    @SpringBootApplication
    @EnableScanner(packages = {"com.boot.condition.bootcondition.simple.entity", "com.boot.condition.bootcondition.simple.bean"})
    public class ScannerPackageApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(ScannerPackageApplication.class, args);
    
            context.close();
        }
    
    }
    
    
    
    import org.springframework.context.annotation.Import;
    
    import java.lang.annotation.*;
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(ScannerPackageRegistrar.class)
    public @interface EnableScanner {
    
        String[] packages();
    }
    

    2.导入需要扫描的注册类 ScannerPackageRegistrar, 将扫描的对象设置到spring容器

    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 〈一句话功能简述〉<br> 
     * 〈〉
     *
     * @author 26918
     * @create 2018/10/17
     * @since 1.0.0
     */
    public class ScannerPackageRegistrar implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
            System.out.println("packages value::"+annotationMetadata.getAnnotationAttributes(EnableScanner.class.getName()));
    
            String[] arrs = (String[]) annotationMetadata.getAnnotationAttributes(EnableScanner.class.getName()).get("packages");
            List<String> packages = Arrays.asList(arrs);
            System.out.println(packages);
    
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(MyBeanDefinitionProcessor.class);
            bdb.addPropertyValue("packages", packages);
    
            beanDefinitionRegistry.registerBeanDefinition(MyBeanDefinitionProcessor.class.getName(), bdb.getBeanDefinition());
        }
    }

    3.定义一个MyBeanDefinitionProcessor implements BeanPostProcessor 用于初始回调对象

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    import java.util.List;
    /**
     * 〈一句话功能简述〉<br> 
     * 〈bean 初始回调〉
     *
     * @author 26918
     * @create 2018/10/17
     * @since 1.0.0
     */
    
    public class MyBeanDefinitionProcessor implements BeanPostProcessor {
    
        private List<String> packages;
    
        public List<String> getPackages() {
            return packages;
        }
    
        public void setPackages(List<String> packages) {
            this.packages = packages;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            for (String pkg : packages) {
                if(bean.getClass().getName().startsWith(pkg)){
                    System.out.println("instance bean:"+bean.getClass().getName());
                }
            }
            return bean;
        }
    }

     

    展开全文
  • Spring Boot 自定义@Enable* 注解@Enable*的实例@EnableAsync通过实现ImportSelector接口来实现bean的加载通过实现ImportBeanDefinitionRegistrar接口来实现bean的加载自定义Enable注解来实现对类加载的监听 ...

    @Enable*的实例@EnableAsync

    在Spring Boot中,当我们想要以多线程的方式来运行某一段代码时,我们可以在方法上面使用注解@Async,但同时,我们有必须在Spring Boot的启动类中配置@EnableAsync来让注解@Async生效,究竟@Enable*都做了什么样的工作,来实现了我们所配置的注解生效呢?
    我们来看一下@EnableAsync的源码

    	@Target({ElementType.TYPE})
    	@Retention(RetentionPolicy.RUNTIME)
    	@Documented
    	@Import({AsyncConfigurationSelector.class})
    	public @interface EnableAsync {
    

    在注解定义中,除了正常使用的@Target@Retention@Documented之外,还有一个@Import的注解,在@Import中有一个AsyncConfigurationSelector的选择器我们再来看一下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;
    		}
    	}
    
    }
    

    可以看到AsyncConfigurationSelector继承了AdviceModeImportSelector,当我们再点进这个父类中看源码的时候可以发现AdviceModeImportSelector实现了ImportSelector这个接口,而ImportSelector这个接口中的方法(String[] selectImports(AnnotationMetadata importingClassMetadata);),通常会返回类实例名称。也就是说只要实现了这个方法,就可以根据不同的场景,返回不同的类实例。

    通过实现ImportSelector接口来实现bean的加载

    通常,我们加载一个类可以通过简单的@Component@Service@Controller等方式让Spring对类进行实例化托管,但我们也可以通过@Import的方式,来实现类的实例化。
    首先我们定义一个等待被实例化的类Book

    package com.boot.enable.bootenable;
    
    public class Book {
    }
    

    实现ImportSelector接口的实现类BeanImportSelector

    package com.boot.enable.bootenable;
    
    import org.springframework.context.annotation.ImportSelector;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class BeanImportSelector implements ImportSelector {
        @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            return new String[] {"com.boot.enable.bootenable.Book"};
        }
    }
    
    启动类
    @SpringBootApplication
    // 使用Import方式装配
    @Import(BeanImportSelector.class)
    public class BootEnableApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(BootEnableApplication.class, args);
            System.out.println(context.getBean(Book.class));
        }
    

    这个时候我们就能正常看到Book这个类已经被实例化了

    通过实现ImportBeanDefinitionRegistrar接口来实现bean的加载

    同样的,我们依旧是使用Book类来作为等待被加载的类
    我们新建一个MyBeanDefinitionRegistrar类来实现ImportBeanDefinitionRegistrar接口

    package com.boot.enable.bootenable;
    
    import org.springframework.beans.factory.support.AbstractBeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            // 创建构建器对象
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Book.class);
            AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
            registry.registerBeanDefinition("book", beanDefinition);
        }
    }
    
    启动类
    @SpringBootApplication
    // 使用Import方式装配
    @Import(MyBeanDefinitionRegistrar.class)
    public class BootEnableApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(BootEnableApplication.class, args);
            System.out.println(context.getBean(Book.class));
        }
    

    同样的,我们也能正常看到Book这个类已经被实例化了。

    自定义Enable注解来实现对类加载的监听

    我们已经知道了@Import可以帮我们对类进行加载,接下来就到本篇文章的重点了,我们该如何实现类似@Enable*的注解来实现对某些类加载的监听呢?
    首先,我们需要一个@Enable的类,我们先创建一个注解@EnableScanner

    package com.boot.enable.bootenable.sample;
    
    import org.springframework.context.annotation.Import;
    
    import java.lang.annotation.*;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @Import(ScannerPackageRegistrar.class)
    public @interface EnableScanner {
        String[] packages();
    }
    

    我们可以看到在@EnableScanner中,我们使用了@Import的注解导入了一个注册类ScannerPackageRegistrar
    我们来看一下ScannerPackageRegistrar这个类

    package com.boot.enable.bootenable.sample;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    import java.util.List;
    
    public class MyBeanDefinitionProcessor implements BeanPostProcessor {
    
        private List<String> packages;
    
        public void setPackages(List<String> packages) {
            this.packages = packages;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            for (String pkg : packages) {
                if (bean.getClass().getName().contains(pkg)) {
                    System.out.println("instance bean" + bean.getClass().getName());
                }
            }
            return bean;
        }
    }
    

    在这个类中,我们实现了BeanPostProcessor接口下的postProcessBeforeInitialization方法,这个方法可以帮我们在实例被加载之前,拿到相关bean的一些信息,同时packages中是我们保存需要被监听的文件的包信息。
    但是,我们只有这些还不够,我们还需要将MyBeanDefinitionProcessor注册进注册器中,我们可以通过实现ImportBeanDefinitionRegistrar的方式来对我们自定义的监听器进行注册

    package com.boot.enable.bootenable.sample;
    
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class ScannerPackageRegistrar implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            String[] attrs = (String[]) importingClassMetadata.getAnnotationAttributes(EnableScanner.class.getName()).get("packages");
            List<String> packages = Arrays.asList(attrs);
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(MyBeanDefinitionProcessor.class);
            builder.addPropertyValue("packages", packages);
            registry.registerBeanDefinition(MyBeanDefinitionProcessor.class.getName(), builder.getBeanDefinition());
        }
    }
    

    我们通过参数importingClassMetadata可以拿到注解的相关属性信息,同时将拿到的packages存放进我们的MyBeanDefinitionProcessor中,这样,我们就等于实现了对类加载的监听。
    接下来,我们进行测试,测试中新写了一个Person类

    package com.boot.enable.bootenable.sample.bean;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Person {
    }
    

    可以发现,现在的Person类通过@Component注解已经交予了Spring容器进行管理
    启动类

    package com.boot.enable.bootenable.sample;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    @EnableScanner(packages = {"com.boot.enable.bootenable.sample.bean"})
    public class ScannerPackageApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(ScannerPackageApplication.class, args);
            context.close();
        }
    
    }
    

    我们运行后就可以得到对类监听的结果了

    com.boot.enable.bootenable.Book@11a82d0f
    
    展开全文
  • springboot-自定义Enable*配置注解

    千次阅读 2019-02-01 14:42:32
    1 定义EnableScanner注解,作用是对指定的packages文件夹下的类进行特殊处理,比如设置特殊值等! ​ package com.cyb.myenable; import java.lang.annotation.Documented; import java.lang.annotation.Element...

    1 定义EnableScanner注解,作用是对指定的packages文件夹下的类进行特殊处理,比如设置特殊值等!

    ​
    package com.cyb.myenable;
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import org.springframework.context.annotation.Import;
     
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(ScannerPackageRegistrar.class)
    public @interface EnableScanner {
     
        String[] packages();
    }
    
    ​

    2 定义注解引入的执行类,并将其注册到spring容器中

    package com.cyb.myenable;
    
    import java.util.Arrays;
    import java.util.List;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    /**
     *作者 : iechenyb<br>
     *类描述: 说点啥<br>
     *创建时间: 2019年2月1日
     */
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class ScannerPackageRegistrar implements ImportBeanDefinitionRegistrar {
    	Log log = LogFactory.getLog(ScannerPackageRegistrar.class);
    
    	public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
    			BeanDefinitionRegistry beanDefinitionRegistry) {
    		System.out.println(
    				"packages value::" + annotationMetadata.getAnnotationAttributes(EnableScanner.class.getName()));
    
    		String[] arrs = (String[]) annotationMetadata.getAnnotationAttributes(EnableScanner.class.getName())
    				.get("packages");
    		List<String> packages = Arrays.asList(arrs);
    		System.out.println(packages);
    
    		BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(MyBeanDefinitionProcessor.class);
    		bdb.addPropertyValue("packages", packages);
    
    		beanDefinitionRegistry.registerBeanDefinition(MyBeanDefinitionProcessor.class.getName(),
    				bdb.getBeanDefinition());
    	}
    }
    

    3 定义bean前后置处理器,对指定包里的类进行特殊的初始化。

    package com.cyb.myenable;
    import java.util.List;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    /**
     *作者 : iechenyb<br>
     *类描述: 所有的bean定义时添加前后处理逻辑<br>
     *创建时间: 2019年2月1日
     */
    public class MyBeanDefinitionProcessor implements BeanPostProcessor{
    	Log log = LogFactory.getLog(MyBeanDefinitionProcessor.class);
    	private List<String> packages;
    	 
        public List<String> getPackages() {
            return packages;
        }
     
        public void setPackages(List<String> packages) {
            this.packages = packages;
        }
     
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            for (String pkg : packages) {
                if(bean.getClass().getName().startsWith(pkg)){
                    System.out.println("instance bean:"+bean.getClass().getName());
                }
            }
            return bean;
        }
    
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    }
    

    4 定义配置类,启动注解

    package com.cyb.myenable;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.context.annotation.Configuration;
    /**
     *作者 : iechenyb<br>
     *类描述: 说点啥<br>
     *创建时间: 2019年2月1日
     */
    @Configuration
    @EnableScanner(packages={"com.cyb.adapter","com.cyb.advice"})
    public class ScannerConfiguration {
    	Log log = LogFactory.getLog(ScannerConfiguration.class);
    }
    

     

    展开全文
  • 如何开发自己的Enable注解? 1.原理 以@EnableScheduling为例,查看其源码,发现添加了一个@Import注解 继续查看@Import注解源码,发现其是由Spring提供的,用来导入配置类的,在配置类中定义的Bean(@Bean),可...
  • spring boot 自定义@EnableXXX注解

    千次阅读 2019-02-24 15:27:10
    spring boot 自带了很多@EnableXXX这样的注解,通过这些注解我们可以很方便地启用某些功能,比如@EnableAutoConfiguration用来开启自动装配的功能。内部实现主要是通过@Import注解将指定的类实例注入之Spring IOC ...
  • Spring Boot @Enable注解源码解析及自定义@Enable Spring Boot 一个重要的特点就是自动配置,约定大于配置,几乎所有组件使用其本身约定好的默认配置就可以使用,大大减轻配置的麻烦。其实现自动配置一个方式就是...
  • 向你展示怎样创建两个自定义注解Annotation---@Test和@TestInfo, 进行单元测试1:@Test 注解这个@interface告诉java这个一个自定义注解,然后你可以使用这个注解在类的方法上使用,例如:@Test(enable...
  • 上一篇大概讲了springboot 的@EnableAutoConfiguration的实现,这篇我们自定义一个@EnableMyCache注解实现。 1.利用@Import注解加载不在包扫描范围的类,并将其注册到容器。 2.我们知道将Bean注册到IOC容器有很多...
  • 因为spring boot会扫描启动类同包及子包中的bean, 而范围以外的bean 就需要用 上面三种方式注入到spring容器中。 比如:注解注解处理类,项目中如果使用jar包中的...spring Boot的 @Enable* 注解就是把引入注解处...
  • spring boot启动的时候会自动扫描启动类上@Enable开头的注解,然后我们可以给@EnableXXX加上注解@Import,导入实现了ImportSelector或ImportBeanDefinitionRegistrar的类 新建spring-boot-stater工程:myTest2-...
  • 其实现自动配置一个方式就是使用@Enable*注解,见其名知其意也,即“使什么可用或开启什么的支持”。Spring Boot 常用@Enable*首先来简单介绍一下Spring Boot 常用的@Enable*注解及其作用吧。@EnableAutoC...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 129
精华内容 51
关键字:

自定义enable注解