精华内容
下载资源
问答
  • springboot-自定义Enable*配置注解
    千次阅读
    2019-02-01 14:42:32

    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注解来开启某些功能。例如 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;
        }
    }

     

    展开全文
  • 自定义@EnableXXX注解

    2021-11-04 17:10:15
    自定义@EnableXXX注解 场景 自定义注解 + AOP 实现接口日志的自动记录(日志记录器),将本项目打包到别的项目上使用时,一开始没有效果,后来发现是因为SpringBoot项目默认注册主程序所在包以及子包的Bean , 而导入...

    自定义@EnableXXX注解

    场景

    自定义注解 + AOP 实现接口日志的自动记录(日志记录器),将本项目打包到别的项目上使用时,一开始没有效果,后来发现是因为SpringBoot项目默认注册主程序所在包以及子包的Bean , 而导入的日志记录器里面的所有Bean都没有注入Spring IOC容器 , 所以在主程序上使用@ComponentScan(basePackages = {“com.lian.song”}) 注解,显式的使得当前项目去注入日志记录器中的Bean ,

    但是这样就暴露出一些问题

    1 包名暴露了

    2 使用起来不是特别的方便

    经过大佬的指定,把注入Bean的功能放到日志记录器中,并且使用@EnableLogger注解实现此功能,使用的时候也能见名知意

    作用

    就是为了解决本项目的Bean不能在本项目注入,而需要在引入项目进行显式注入的问题(本项目的Bean由本项目注入)

    自定义

    第一步 定义一个配置文件,将本项目中所有Bean都返回并且使其配置文件和Bean定义能够被扫描

    @Configuration
    public class LoggerConfig {
       // 一定要注入所有的Bean
    
        @Bean
        public LoggingAspects getLoggingAspects() {
            return new LoggingAspects();
        }
    
        @Bean
        public LogMapper getLogMapper() {
            return new DefaultLogMapperImpl();
        }
    
        @Bean
        public LoggingUtils getLoggingUtils() {
            return new LoggingUtils();
        }
    
        @Bean
        public SpringUtils getSpringUtils() {
            return new SpringUtils();
        }
    }
    

    2 自定义一个注解(@EnableXXX),用于在别的项目使用时开启特定功能(本质就是注入特定的功能所需要的Bean)

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(LoggerEnableAutoConfig.class)  //关注@Import() 注解及其导入的配置类
    public @interface EnableLogger {
    
    }
    

    到现在为止,知道@EnableLogger注解用于注入项目的Bean , 用在别的项目的主程序上,但是这个注解用在了那个主程序上,别的项目的主程序和本项目的配置文件是怎么勾连上的呢?这时候就是

    @Import(LoggerEnableAutoConfig.class)  
    

    发挥作用的时候了

    看名字就知道@Import注解导入一个自动配置类(LoggerEnableAutoConfig)

    第三步 自定义自动配置类

    @Slf4j
    @Configuration
    public class LoggerEnableAutoConfig implements ImportSelector {
        Logger logger = LoggerFactory.getLogger(LoggerEnableAutoConfig.class);
    
        @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            //判断主程序上是否存在指定注解
            Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(EnableLogger.class.getName());
            if(attributes == null){
                log.info("@EnableLogger is not used on the main program");
                return new String[0];
            }
            return  new String[]{LoggerConfig.class.getName()};
        }
    
    
    }
    

    编写一个实现了ImportSelector接口类

    ImportSelector接口,查看其具体实现源码(根据AnnotationMetadata元数据注册bean类,即返回的Bean 会自动的被注入,被Spring所管理)

    public interface ImportSelector {
    
    	/**
    	 * Select and return the names of which class(es) should be imported based on
    	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
    	 * @return the class names, or an empty array if none
    	 */
    	String[] selectImports(AnnotationMetadata importingClassMetadata);
        
    }
    

    这个接口返回的类的全类名对应的Bean都会被注入到IOC容器中

    其实现自动配置的方式的底层就是通过@Import注解引入相关配置类,然后再在配置类将所需的bean注册到spring容器中和实现组件相关处理逻辑

    展开全文
  • spring boot 自定义@EnableXXX注解

    千次阅读 2019-02-24 15:27:10
    spring boot 自带了很多@EnableXXX这样的注解,通过这些注解我们可以很方便地启用某些功能,比如@EnableAutoConfiguration用来开启自动装配的功能。内部实现主要是通过@Import注解将指定的类实例注入之Spring IOC ...
  • Spring Boot @Enable注解源码解析及自定义@Enable Spring Boot 一个重要的特点就是自动配置,约定大于配置,几乎所有组件使用其本身约定好的默认配置就可以使用,大大减轻配置的麻烦。其实现自动配置一个方式就是...
  • 我们经常会遇到@Enable开始的好多注解,比如@EnableWebMvc、@EnableEurekaServer、@EnableAsync、@EnableScheduling等,今天我们就来分析下这些注解到底是如何工作的,并写手自定的@Enable注解。 @Enable*实现的原理...
  • 因为spring boot会扫描启动类同包及子包中的bean, 而范围以外的bean 就需要用 上面三种方式注入到spring容器中。 比如:注解注解处理类,项目中如果使用jar包中的...spring Boot的 @Enable* 注解就是把引入注解处...
  • 16-SpringBoot自动配置-Enable注解原理Enable注解原理@Enable* 注解SpringBoot提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。...
  • Spring Boot 自定义@Enable* 注解@Enable*的实例@EnableAsync通过实现ImportSelector接口来实现bean的加载通过实现ImportBeanDefinitionRegistrar接口来实现bean的加载自定义Enable注解来实现对类加载的监听 ...
  • 上一篇大概讲了springboot 的@EnableAutoConfiguration的实现,这篇我们自定义一个@EnableMyCache注解实现。 1.利用@Import注解加载不在包扫描范围的类,并将其注册到容器。 2.我们知道将Bean注册到IOC容器有很多...
  • 这篇文章主要介绍了springBoot @Enable* 注解的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 1、为什么使用@SpringBootApplication注解,即可做到自动配置? 答:@...
  • 1. maven配置 首先需要在maven的pom文件中配置依赖。... 使用自定义注解打印 自定义注解定义完成,可以在我们的方法上面来使用这个注解了,使用如下图 调用该方法时,就可以看到该注解所打印的日志了
  • spring boot启动的时候会自动扫描启动类上@Enable开头的注解,然后我们可以给@EnableXXX加上注解@Import,导入实现了ImportSelector或ImportBeanDefinitionRegistrar的类 新建spring-boot-stater工程:myTest2-...
  • SpringBoot手动装配,自定义Enable模块

    千次阅读 2020-08-12 19:35:28
    今天这篇文章主要是介绍下如何是实现手动配置,自定义Enable模块,
  • Spring-Boot之@Enable*注解的工作原理

    千次阅读 2018-10-16 22:28:33
    @enable*是springboot中用来启用某一个功能特性的一类注解。其中包括我们常用的@SpringBootApplication注解中用于开启自动注入的annotation@EnableAutoConfiguration,开启异步方法的annotation@EnableAsync,开启将...
  • 自定义注解扫描

    2020-08-16 13:55:24
    扫描自定义注解有多种方式,这里通过实现ImportBeanDefinitionRegistrar类来进行自定义注解的扫描,并将其注入IOC容器中。ImportBeanDefinitionRegistrar类本身只能通过@Import方式进行注入,所以先来实现一个注解...
  • 【spring】自定义缓存注解

    千次阅读 2022-04-26 13:49:43
    为什么要自定义缓存注解? Spring Cache本身提供@Cacheable、@CacheEvict、@CachePut等缓存注解,为什么还要自定义缓存注解呢? @Cacheabe不能设置缓存时间,导致生成的缓存始终在redis中,当然这一点可以通过修改...
  • Spring-boot|如何自定义@Enable模块装配

    千次阅读 2018-12-16 23:13:26
    在学习SpringBoot的时候,我们会使用到@Enable***注解的地方,使用上也都是加在@Configuration 类注解的类上面,比如: (1)@EnableAutoConfiguration 开启自动扫描装配Bean (2)@EnableScheduling 开启计划任务的...
  • 设置myboot.enable=true或者缺省,然后设置myboot.status=OK和myboot.msg=hello myboot stater,再次启动 >>> spring boot 启动完成 自定义条件注解@MyConditionAnnotation @MyConditionAnnotation @Target({ ...
  • 文章目录前言第一节、问题:引入一个jar能直接获取它的Bean吗pojo工程enable工程(引入pojo)第二节、如何获取到user这个Bean第一种、配置@ComponentScan第二种、配置@Import注解第三种、 配置@Enable注解 前言 @Enable...
  • springBoot @Enable* 注解

    2018-06-05 14:50:23
    1、为什么使用@SpringBootApplication注解,即可做到自动配置? 答:@SpringBootApplication,内部起作用的注解其实有3个。@EnableAutoConfiguration,@ComponentScan,@Configuration。这篇文章主要是讲解@EnableXX...
  • 注解,@Import
  • 自定义鉴权注解与AOP

    2022-03-16 20:13:03
    } 自定义注解: /** * 鉴权注解 * */ @Target(ElementType.METHOD) // 注解范围,注解使用在方法上 @Retention(RetentionPolicy.RUNTIME) // 生效时间 @Documented public @interface Authenticate { /** * 服务code...
  • 在Java中,类使用class定义,接口使用interface定义,注解和接口的定义差不多,增加了一个@符号,即@interface,代码如下: public @interface EnableAuth { } 注解中可以定义成员变量,用于信息的描述,跟接口中...
  • 使用Aop实现自定义注解- 原理篇 使用Aop实现自定义注解 - 实战篇(统一日志打印) 统一日志打印 约定大于配置,系统提供对外的接口要有以下要求,这样的好处是我们可以对接口统一做定制化日志管理。比如只对更新接口...
  • 四、使用自定义注解 @EnableAuth @PostMapping(value = "/login") public ResultData login(String username, String password) { logger.info("------用户登录 login:{} start", "username:" + username + ...
  • 考虑到并不是所有的请求都需要进行参数校验,这还可以有另一种实现方法: 自定义注解@ 1、自定义注解接口 import java.lang.annotation.*; //注解信息会被添加到Java文档中 @Documented //注解的生命周期,表示注解...
  • 经常会用到Spring项目中@EnableXXX这种注解,都是用来启用某种功能,这种注解类似于一种开关,加了这个注解,就能使用某些功能。例如@EnableAsync、@EnableScheduling 等注解。 Srping实现Enable模块驱动的方法大致...
  • ​ 声明:SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态开启某些功能的,而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载,第三方jar包中的也可以通过此注解进行配置 ​ @Enable底层...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,636
精华内容 5,454
关键字:

自定义enable注解