• Sping 源码理解(一)注解驱动


    1 组件添加

     

        /**
         * 给容器中注册组件
         * 1》包扫描+组件标注注解(@Controller @Service @Repository @Component [自己写的类])
         * 2》@Bean [导入的第三方包里面的组件]
         * 3》@Import [快速给容器中导入一个组件]
         *    1)@Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名
         *    2)ImportSelector:返回需要导入的组件的全类名数组;
         *    3)ImportBeanDefinitionRegistrar: 手动注册bean到容器中
         * 4》使用Spring提供的FactoryBean(工厂bean)
         *       1)默认获取奥的是工厂bean调用getObject创建的对象
         *       2)要获取工厂bean本身,我们需要给id前面加一个&
         *          &colorFactoryBean
         *
         */

        除了 @Controller  @Service  @Repository  @Component基本方式以外;还可以通过 @Configuration   @Bean  @ComponentScan(自动扫描组件TypeFilter过滤)  @ Import 的方式添加组件

     Test.java

        @Test
        public void test01() {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
            for (String name : beanDefinitionNames) {
                System.out.println(name);
            }
            Object person = applicationContext.getBean("person");
            Object person1 = applicationContext.getBean("person");
            System.out.println(person == person1);
        }

    MainConfig.class

    //配置类==配置文件
    @Configuration
    @ComponentScan(value = "com", includeFilters = {
    //        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),   注解类型
    //        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}), //制定类型过滤
            @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})  //自定义
    }, useDefaultFilters = false)//默认过滤开关
    //excludeFilters = filter[]
    //includeFilters= filter[]  useDefaultFilters = false关闭默认过滤规则,扫描只包含哪些组件
    //componentScan value制定要扫描的包
    //FilterType.ANNOTATION:按照注解
    public class MainConfig {
    
        //给容器中注册一个bean;类型为返回值的类型,id默认使用方法名作为id
        @Bean
        public Person person() {
            return new Person("lisi", 20);
        }
    }

    MyTypeFilter.class

    public class MyTypeFilter implements TypeFilter {
        /**
         *
         * @param metadataReader 当前正在扫描的类的信息
         * @param metadataReaderFactory 可以获取到其他任何类信息的
         * @return
         * @throws IOException
         */
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
            //获取当前类注解的信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            //获取当前正在扫描的类的类信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            //获取当前类资源信息(类的路径)
            Resource resource = metadataReader.getResource();
    
            String className = classMetadata.getClassName();
            System.out.println("----->>" + className);
           // if (className.contains("er")) {return true;}
    
            return false;
        }
    }

    结果:

     2 @ Import 添加  @scope 调整作用域

      MainConfig2

    //满足当前条件,这个类中配置的所以bean注册才能生效
    //@Conditional({LinuxCondition.class})
    @Configuration
    //导入组件,id默认是组件的全类名
    @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
    public class MainConfig2 {
        //默认是单实例的
        //@scope 调整作用域
        //prototype(多实例)  singleton(默认的)ioc启动会调用方法创建对象放到ioc容器中  request(同一次请求创建一个实例)  session(同一个session创建一个实例)
    
        /**
         * 懒加载:
         *     单实例bean:默认在容器启动的时候创建对象
         *     懒加载:容器启动不加载。第一次使用(获取)bean创建对象,并进行初始化
         * @return
         */
    //    @Scope("prototype")
        @Lazy
        @Bean(value = "person")
        public Person person(){
            System.out.println("给容器添加person");
            return new Person("张三", 25);
        }
    
    
        /**
         * @conditional({condition}) :按照一定的条件进行判断,满足条件给容器中注册bean
         * 如果是Windows 注册bill
         * 如果是Linux 注入 linas
         */
        @Conditional({WindowsCondition.class})
        @Bean("bill")
        public Person person01() {
            return new Person("Bill Gates", 62);
        }
    
    
        @Bean("linas ")
        public Person person02() {
            return new Person("linas", 70);
        }
    
        /**
         * 给容器中注册组件
         * 1》包扫描+组件标注注解(@Controller @Service @Repository @Component [自己写的类])
         * 2》@Bean [导入的第三方包里面的组件]
         * 3》@Import [快速给容器中导入一个组件]
         *    1)@Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名
         *    2)ImportSelector:返回需要导入的组件的全类名数组;
         *    3)ImportBeanDefinitionRegistrar: 手动注册bean到容器中
         * 4》使用Spring提供的FactoryBean(工厂bean)
         *       1)默认获取奥的是工厂bean调用getObject创建的对象
         *       2)要获取工厂bean本身,我们需要给id前面加一个&
         *          &colorFactoryBean
         *
         */
        @Bean
        public ColorFactoryBean colorFactoryBean(){
            return new ColorFactoryBean();
        }
    }


    MyImportSelector.class

    //自定义逻辑返回需要导入的组件
    public class MyImportSelector implements ImportSelector {
    
        //返回值,就是到导入到容器中的组件全类名
        //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            //importClassMetadata
            //
            return new String[]{"com.bean.Blue","com.bean.Yellow"};
        }
    }
    MyImportBeanDefinitionRegistrar.class
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        /**
         *
         * @param importingClassMetadata 当前类的注解信息
         * @param registry BeanDefinition注册类
         *                把所以需要添加到容器中的bean:调用BeanDefinitionRegistry.registerBeanDefinition手工注册进来
         */
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            boolean red = registry.containsBeanDefinition("com.bean.Red");
            if (red) {
                //制定Bean定义信息(Bean的类型,Bean)
                RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
                //注册一个Bean,指定bean名
                registry.registerBeanDefinition("rainBow", rootBeanDefinition);
            }
    
        }
    }
  • 相关阅读:
    .NET5微服务示例-Ocelot网关
    .NET5微服务示例-Polly熔断与降级
    .NET5微服务示例-Consul注册中心
    .NET下使用ELK日志中心
    [ 题解 ] [ 数学 ] [ JZOJ5809 ] 数羊
    [ 题解 ] [ 数学 ] 函数 (sequence) (欧拉函数)
    [ 题解 ] [ JZOJ5777 ] 小 x 玩游戏
    更换谷歌浏览器视频输入源
    axios 封装及 API 接口管理
    小程序代码压缩实践
  • 原文地址:https://www.cnblogs.com/misliu/p/15480335.html
Copyright © 2020-2023  润新知