zoukankan      html  css  js  c++  java
  • spring源码阅读(五)Spring Import注解使用

    说明

    我们再读源码时常常发现这个注解,近期在读dubbo源码 就使用到了此注解,究竟有什么用,在spring boot项目中尤其多

    Import的作用

    实现将打了@Import的注解注入到容器,以及@Import指定的类注入到容器

    import的三种使用方式

    直接导入指定类的方式

    1.定义一个打上了Import的类

    /**
     * student和BeanRegisterConfig都会初始化进入容器 student的beanName为类的全名称
     */
    @Import({Student.class})
    public class BeanRegisterConfig  {
    }

    2.main测试

    public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(BeanRegisterConfig.class);  //这里的参数代表要做操作的类
            String [] names=applicationContext.getBeanDefinitionNames();
            for (String name:
            names) {
                System.out.println(name);
            }
        }

    3.输出

    导入ImportSelector方式

    允许我们自定义导入的类

    1.定义一个ImportSelector类

    public class BeanRegisterImportSelector implements ImportSelector {
    
        /**
         *
         * @param importingClassMetadata 注解元数据
         * @return 返回值为要初始化的类的全名称
         */
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            for (String typeName :
                    importingClassMetadata.getAnnotationTypes()) {
                System.out.println("typeName" + typeName);
            }
            //告诉容器初始化importtest.bean.Student
            return new String[]{"importtest.bean.Student"};
        }
    }

    2.定义一个打上了Import的类 导入BeanRegisterImportSelector

    @Import({BeanRegisterImportSelector.class})
    public class BeanRegisterConfig  {
    
    }

    3.测试

        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(BeanRegisterConfig.class);  //这里的参数代表要做操作的类
            String [] names=applicationContext.getBeanDefinitionNames();
            for (String name:
            names) {
                System.out.println(name);
            }
        }

    导入ImportBeanDefinitionRegistrar方式

    ImportBeanDefinitionRegistrar 允许我们拿到BeanDefinitionRegistry 实现自定义注册

    1.定义ImportBeanDefinitionRegistrar实现类

    public class BeanRegisterImportBeanDefinitionRegistrar  implements ImportBeanDefinitionRegistrar {
        /**
         *
         * @param importingClassMetadata 为@Import类的相关注解
         * @param registry current bean definition registry
         */
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            for (String typeName :
                    importingClassMetadata.getAnnotationTypes()) {
                System.out.println("typeName" + typeName);
            }
            BeanDefinition beanDefinition=new RootBeanDefinition();
            beanDefinition.setBeanClassName("importtest.bean.Student");
               registry.registerBeanDefinition("student",beanDefinition);
        }
    }

    2.定义import导入ImportBeanDefinitionRegistrar实现类

    @Import({BeanRegisterImportBeanDefinitionRegistrar.class})
    public class BeanRegisterConfig  {
    
    }

    3.main测试

        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(BeanRegisterConfig.class);  //这里的参数代表要做操作的类
            String [] names=applicationContext.getBeanDefinitionNames();
            for (String name:
            names) {
                System.out.println(name);
            }
        }

    例子通过Import实现自动化配置

    1.定义配置文件canalClient.properties

    canal.host=127.0.0.1
    canal.port=9081

    2.定义CanalClientInitConfig 配置

    public class CanalClientInitConfig implements InitializingBean {
            @Value("${canal.host}")
            private String canalServerIp;
            @Value("${canal.port}")
            private String canalPort;
    
            /**
             * 利用spring生命周期
             * @throws Exception
             */
            @Override
            public void afterPropertiesSet() throws Exception {
                /**
                 * 模拟自动监听 这里可以写自己的自动监听代码
                 */
                System.out.println("开始监听host:"+canalServerIp+",port:"+canalPort);
            }
        }

    3.定义ImportBeanDefinitionRegistrar实现类

    public class CanalImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
        private  Environment environment;
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            //通过spring生命周期的InitializingBean 进行自动监听
            //原RootBeanDefinition rootBeanDefinition=new RootBeanDefinition(CanalClientInitConfig.class);
            //参考优化后:https://www.cnblogs.com/LQBlog/p/12420860.html#autoid-4-2-0
            //建造者模式,生成ServiceAnnotationBeanPostProcessor BeanDefinition的builder
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CanalClientInitConfig.class);
            AbstractBeanDefinition rootBeanDefinition=builder.getBeanDefinition();
            registry.registerBeanDefinition("canalClientInitConfig",rootBeanDefinition);
    
        }
    
        /**
         * Set the {@code Environment} that this component runs in.
         *
         * @param environment
         */
        @Override
        public void setEnvironment(Environment environment) {
            this.environment=environment;
        }
    }

    4.定义启动注解

    @Target({ElementType.TYPE})//只能打在类上
    @Retention(RetentionPolicy.RUNTIME)//保留到运行时
    @Import(value = CanalImportBeanDefinitionRegistrar.class)
    @Inherited
    public @interface EnableCanalClient {
    }

    5.启用canlaClient

    @EnableCanalClient
    //spring注解方式 加载此路径的properties 到容器
    @PropertySource("classpath:canalClient.properties")
    public class BeanRegisterConfig {
    }

    6.man测试

    public class CanalClientMain {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(BeanRegisterConfig.class);  //这里的参数代表要做操作的类
            String [] names=applicationContext.getBeanDefinitionNames();
            for (String name:
                    names) {
                System.out.println(name);
            }
        }
    }

    7.输出

  • 相关阅读:
    nginx中的超时配置
    ubuntu系统TCP连接参数优化-TIME_WAIT过多解决办法
    python中的raise用法
    pip安装各种模块
    ubuntu上安装python的ldap模块
    docker 打印带时间的日志
    基于Xilinx Zynq Z7045 SoC的CNN的视觉识别应用
    VIVADO下IBERT使用指南
    菜根谭全文及译文
    bit,Byte,Word,DWORD(DOUBLE WORD,DW)
  • 原文地址:https://www.cnblogs.com/LQBlog/p/15410425.html
Copyright © 2011-2022 走看看