zoukankan      html  css  js  c++  java
  • Spring注解驱动开发04(给容器中注册组件的方式)

    给容器中注册组件的三种方式

    1. 组件注解标注 + 包扫描(适用于自己写的类)

    //控制层组件
    @Controller
    public class PersonController {
    }
    
    //业务逻辑层组件
    @Service
    public class PersonServic {
    }
    
    //持久层组件
    @Repository
    public class PersonDao {
    }
    
    //其他组件
    @Component
    public class Person {
    }
    

    包扫描(注解或者xml的方式)

    1.使用注解的方式
    @ComponentScan(value = "com.xxx")
    
    2.使用xml的方式
    <context:component-scan base-package="com.xxx"/>    
    

    2. @Bean(适用于第三方包里面的组件)

    了解@Bean使用详情

    @Bean("组件id") 默认使用方法名作为id,返回值作为组件的类型
    

    3. @Import(快速给容器中导入一个组件)

    @Import的第一种用法

    1. 直接在配置类上加上注解@Import(要加入到ioc容器中的类的类模板)
    @Configuration
    @ComponentScan(value = "com.atguigu",excludeFilters = {
            //不扫描@controller和service注解,type默认为注解类型,可以不写
            @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {Myfilter.class})})
    @SuppressWarnings("all")
    @Import(HashMap.class)  //将HashMap类加入到ioc容器中
    public class MainConfig {
    }
    

    可以看到@Import注解的value时个数组,所以也可以导入多个值
    注意:@Import注入的bean默认id为类的全限定名

    public @interface Import {
    
    	/**
    	 * {@link Configuration @Configuration}, {@link ImportSelector},
    	 * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
    	 */
    	Class<?>[] value();
    
    }
    
    @Import(HashMap.class,TreeMap.class)  //将HashMap类加入到ioc容器中
    public class MainConfig {
    }
    
    1. 编写测试类
        @Test
        public void testImport(){
            try(ConfigurableApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class)) {
                //查看容器中的所有对象
                String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
                for (String beanDefinitionName : beanDefinitionNames) {
                    System.out.println(beanDefinitionName);
                }
            }
        }
    
    1. 查看打印结果
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig
    personController
    personServic
    java.util.HashMap  //可以看到ioc容器中已经有hashmap
    java.util.TreeMap  //可以看到ioc容器中已经有treemap
    person
    p1
    

    @Import的第二种用法:ImportSelector方式【重点】

    这种方式的前提就是一个类要实现ImportSelector接口,假如我要用这种方法,目标对象是Myclass这个类,分析具体如下:

    1. 创建Myclass类并实现ImportSelector接口
    //自定义逻辑返回需要导入的组件
    public class MyClass implements ImportSelector {
    
        /**
         * @param importingClassMetadata 表示当前被@Import注解给标注的所有注解信息【不是重点】
         * @return 就是我们实际上要导入到容器中的组件全类名【重点 】
         */
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return new String[]{
                "java.util.LinkedHashSet",
                "java.util.ArrayList"
            };
        }
    
    }
    
    1. 在@Import注解上加入属性自定义类
    @Import({HashMap.class, TreeMap.class, MyClass.class})
    
    1. 测试类
        @Test
        public void testImport(){
            try(ConfigurableApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class)) {
                System.out.println(ioc);
                //查看容器中的所有对象
                String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
                for (String beanDefinitionName : beanDefinitionNames) {
                    System.out.println(beanDefinitionName);
                }
            }
        }
    
    1. 查看打印结果
      打印结果

    @Import的第三种用法:ImportBeanDefinitionRegistrar方式

    同样是一个接口,类似于第二种ImportSelector用法,相似度80%,只不过这种用法比较自定义化注册,具体如下:

    第一步:创建Myclass2类并实现ImportBeanDefinitionRegistrar接口

    public class Myclass2 implements ImportBeanDefinitionRegistrar {
    //该实现方法默认为空
        @Override
        public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
          
        }
    }
    

    参数分析:

    • 第一个参数:annotationMetadata 和之前的ImportSelector参数一样都是表示当前被@Import注解给标注的所有注解信息
    • 第二个参数表示用于注册定义一个bean

    第二步:编写代码,自定义注册bean

    public class Myclass2 implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
            //指定bean定义信息(包括bean的类型、作用域...)
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemo4.class);
            //注册一个bean指定bean名字(id)
            beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition);
        }
    }
    

    第三步:编写TestDemo 类,并标注上使用ImportBeanDefinitionRegistrar方式的Myclass2类

    @Import({TestDemo2.class,Myclass.class,Myclass2.class})
    public class TestDemo {
    
            @Bean
            public AccountDao2 accountDao222(){
                return new AccountDao2();
            }
    
    }
    

    第四步:运行结果

    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig
    personController
    personServic
    java.util.HashMap
    java.util.TreeMap
    java.util.LinkedHashSet
    java.util.ArrayList
    person
    p1
    TestDemo4444 //可以看到已经在ioc中
    

    4. @Import注解的三种使用方式总结

    第一种用法:@Import({ 要导入的容器中的组件 } ):容器会自动注册这个组件,id默认是全类名
    
    第二种用法:ImportSelector:返回需要导入的组件的全类名数组,springboot底层用的特别多【重点 】
    
    第三种用法:ImportBeanDefinitionRegistrar:手动注册bean到容器
    

    以上三种用法方式皆可混合在一个@Import中使用,特别注意第一种和第二种都是以全类名的方式注册,而第三中可自定义方式。
    @Import注解本身在springboot中用的很多,特别是其中的第二种用法ImportSelector方式在springboot中使用的特别多,尤其要掌握!

    课堂无作为,Code写春秋
  • 相关阅读:
    第十五章:Spring Boot 与 开发热部署
    第一章:(1)分布式基础理论
    第一章:(4)Dubbo 案例 HelloWorld
    第一章:(2)Dubbo核心概念
    第十四章:(3)Spring Boot 与 分布式 之 SpringCloud
    web安全测试AppScan扫描工具
    Cheatsheet: 2013 02.01 ~ 02.15
    Cheatsheet: 2013 04.17 ~ 04.30
    Cheatsheet: 2013 02.16 ~ 02.28
    Cheatsheet: 2013 01.21 ~ 01.31
  • 原文地址:https://www.cnblogs.com/hea2t/p/13531020.html
Copyright © 2011-2022 走看看