美文网首页
Spring使用注解注册组件

Spring使用注解注册组件

作者: JBryan | 来源:发表于2020-01-18 11:47 被阅读0次
    环境搭建

    新建Maven项目spring-annotation-demo,添加Maven依赖

    <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>4.3.12.RELEASE</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/junit/junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
    </dependencies>
    
    1.使用@Configuration和@Bean给容器中注册组件

    新建bean包,Person类。三个属性:name,age,nickName。添加有参,无参,toString()方法。

    package com.ljessie.bean;
    
    import org.springframework.beans.factory.annotation.Value;
    
    public class Person {
    
        private String name;
        private Integer age;    
        private String nickName;
    
        public String getNickName() {
            return nickName;
        }
        public void setNickName(String nickName) {
            this.nickName = nickName;
        }
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", nickName='" + nickName + '\'' +
                    '}';
        }
        public Person() {
        }
        public Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
    }
    
    

    新建config包,MainConfig类。在类名上添加@Configuration,告诉Spring,这是一个配置类;然后新建getPerson()方法,添加@Bean注解

    package com.ljessie.config;
    
    import com.ljessie.bean.Person;
    import com.ljessie.service.BookService;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.stereotype.Controller;
    import org.springframework.stereotype.Service;
    
    /**
     * 配置类等同于配置文件
     */
    //告诉Spring,这是一个配置类
    @Configuration
    public class MainConfig {
    
        //给容器中注册一个Bean,类型为返回值的类型,
        @Bean(value = "Person")
        public Person getPerson(){
            return new Person("Bowen",19);
        }
    
    }
    

    在src/main/test下,新建测试类IOCTest,新建test01()方法,添加@Test注解。创建annotationConfigApplicationContext 对象加载MainConfig配置类,然后打印容器中定义的

    package com.ljessie.test;
    
    import com.ljessie.bean.Person;
    import com.ljessie.config.MainConfig;
    import com.ljessie.config.MainConfig2;
    import org.junit.Test;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.core.env.ConfigurableEnvironment;
    
    public class IOCTest {
       
        @Test
        public void test01(){
            AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
            String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
            for (String name:beanDefinitionNames) {
                System.out.println(name);
            }
            Person person = (Person) annotationConfigApplicationContext.getBean("Person");
            System.out.println(person);
        }
    

    运行结果

    一月 17, 2020 11:34:44 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Fri Jan 17 11:34:44 CST 2020]; root of context hierarchy
    一月 17, 2020 11:34:44 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
    信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
    org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Fri Jan 17 11:34:44 CST 2020]; root of context hierarchy
    
    一月 17, 2020 11:34:44 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3e3047e6: startup date [Fri Jan 17 11:34:44 CST 2020]; root of context hierarchy
    一月 17, 2020 11:34:44 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
    信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig
    Person
    Person{name='Bowen', age=19, nickName='null'}
    
    
    2.@ComponentScan-自动扫描和指定扫描规则

    新建component包,ComponentController添加@Controller,ComponentService添加@Service,ComponentDao添加@Repository。

    package com.ljessie.component;
    
    import org.springframework.stereotype.Controller;
    
    @Controller
    public class ComponentController {
    }
    
    
    package com.ljessie.component;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class ComponentService {
    }
    
    
    package com.ljessie.component;
    
    import org.springframework.stereotype.Repository;
    
    @Repository
    public class ComponentDao {
    }
    
    

    在MainConfig类上面添加@Component注解。@ComponentScan属性:Value,指定要扫描的包;

    package com.ljessie.config;
    
    import com.ljessie.bean.Person;
    import com.ljessie.component.ComponentService;
    import com.ljessie.controller.BookController;
    import com.ljessie.service.BookService;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.stereotype.Controller;
    import org.springframework.stereotype.Service;
    
    /**
     * 配置类等同于配置文件
     */
    //告诉Spring,这是一个配置类
    @Configuration
    //value指定要扫描的包,
    // excludeFilters排除要扫描的组件,
    // includeFilters只扫描指定的组件,后面要加上useDefaultFilters
    @ComponentScan(value = "com.ljessie.component")
    public class MainConfig {
    
        //给容器中注册一个Bean,类型为返回值的类型,
        @Bean(value = "Person")
        public Person getPerson(){
            return new Person("Bowen",19);
        }
    
    }
    

    运行test01():componentController,componentDao,componentService注册进来了

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig
    componentController
    componentDao
    componentService
    Person
    Person{name='Bowen', age=19, nickName='null'}
    

    includeFilters:只扫描指定的组件,后面要加上useDefaultFilters。可以指定组件的注解,类型和自定义过滤规则。

    @ComponentScan(value = "com.ljessie.component"
    ,includeFilters = {
                //指定组件的注解
                @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
                //指定组件的类型
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = ComponentService.class),
    //            自定义过滤器
    //            @ComponentScan.Filter(type = FilterType.CUSTOM,classes = CustomFilter.class)
    }, useDefaultFilters = false
    )
    public class MainConfig {
    
        //给容器中注册一个Bean,类型为返回值的类型,
        @Bean(value = "Person")
        public Person getPerson(){
            return new Person("Bowen",19);
        }
    
    }
    

    运行test01():只注册了componentController和componentService,componentDao并没有被注册进来。

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig
    componentController
    componentService
    Person
    Person{name='Bowen', age=19, nickName='null'}
    

    CustomFilter自定义过滤规则,如果组件中包含Controller,则注册。

    package com.ljessie.component;
    
    import org.springframework.core.type.AnnotationMetadata;
    import org.springframework.core.type.ClassMetadata;
    import org.springframework.core.type.classreading.MetadataReader;
    import org.springframework.core.type.classreading.MetadataReaderFactory;
    import org.springframework.core.type.filter.TypeFilter;
    
    import java.io.IOException;
    
    public class CustomFilter implements TypeFilter {
        /**
         *
         * @param metadataReader 读取到的正在扫描类的信息
         * @param metadataReaderFactory 可以获取到的其他类的信息
         * @return
         * @throws IOException
         */
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
    
            //获取当前类的注解的信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    
            //获取当前类的类型信息
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            String className = classMetadata.getClassName();
            System.out.println("-------->"+className);
    
            //获取当前类的资源信息(路径等)
           metadataReader.getResource();
    
           if(className.contains("Controller")){
               return true;
           }
            return false;
        }
    }
    

    注掉includeFilters其他指定。

    @ComponentScan(value = "com.ljessie.component"
    //        , excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})}
            ,includeFilters = {
                //指定组件的注解
    //            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
                //指定组件的类型
    //            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = ComponentService.class),
    //            自定义过滤器
                @ComponentScan.Filter(type = FilterType.CUSTOM,classes = CustomFilter.class)
    }, useDefaultFilters = false
    )
    public class MainConfig {
    //省略其他代码
    }
    

    运行test01():只有componentController被注册进来了

    一月 18, 2020 11:27:14 上午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@475e586c: startup date [Sat Jan 18 11:27:14 CST 2020]; root of context hierarchy
    -------->com.ljessie.component.ComponentController
    -------->com.ljessie.component.ComponentDao
    -------->com.ljessie.component.ComponentService
    -------->com.ljessie.component.CustomFilter
    一月 18, 2020 11:27:14 上午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
    信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig
    componentController
    Person
    Person{name='Bowen', age=19, nickName='null'}
    

    excludeFilters:排除要扫描的组件

    @ComponentScan(value = "com.ljessie.component"
            , excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})}
    )
    public class MainConfig {
    //省略其他代码
    }
    

    运行test01():只有componentDao被注册进来了,排除了componentController和componentService。

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig
    componentDao
    Person
    Person{name='Bowen', age=19, nickName='null'}
    
    3.@Scope调整作用域

    "singleton"; 单例,也是默认值。IOC容器启动会调用方法,创建对象到容器中,以后每次获取,从容器中拿。
    "prototype"; 多实例。IOC容器启动,并不会调用方法,创建对象;而是每次获取的时候,才会调用方法,创建对象。
    新建MainConfig2

    package com.ljessie.config;
    
    import com.ljessie.bean.Color;
    import com.ljessie.bean.ColorFactoryBean;
    import com.ljessie.bean.Person;
    import com.ljessie.bean.Red;
    import com.ljessie.condition.LinuxCondition;
    import com.ljessie.condition.MyImportBeanDefinitionRegistrar;
    import com.ljessie.condition.MyImportSelector;
    import com.ljessie.condition.WindowsCondition;
    import org.springframework.context.annotation.*;
    
    @Configuration
    public class MainConfig2 {
    
    
        /**
         * @Scope:调整作用域
         * String SCOPE_SINGLETON = "singleton"; 单例,也是默认值。IOC容器启动会调用方法,创建对象到容器中,以后每次获取,从容器中拿
         * String SCOPE_PROTOTYPE = "prototype"; 多实例。IOC容器启动,并不会调用方法,创建对象;而是每次获取的时候,才会调用方法,创建对象。
         * @return
         */
        @Scope("prototype")
        @Bean("zhangsan")
        public Person person(){
            System.out.println("给容器中添加person....");
            return new Person("zhangsan",25);
        }
    }
    

    在IOCTest里面新建test02()方法

     @Test
        public void test02(){
            AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
            String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
            for (String name:beanDefinitionNames) {
                System.out.println(name);
            }
            System.out.println("容器创建完成");
            Person person1 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
            Person person2 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
            System.out.println(person1 == person2);
        }
    

    运行结果:先创建容器,然后调用annotationConfigApplicationContext.getBean()方法时,才会创建Person实例,而且创建的两个实例不是同一对象。

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    zhangsan
    容器创建完成
    给容器中添加person....
    给容器中添加person....
    false
    
    4.@Lazy懒加载

    单实例bean:默认容器启动时,创建对象;懒加载,在第一次获取对象的时候,创建对象,并进行初始化。
    MainConfig2里面person()方法去掉@Scope,添加@Lazy

        @Lazy
        @Bean("zhangsan")
        public Person person(){
            System.out.println("给容器中添加person....");
            return new Person("zhangsan",25);
        }
    

    运行test02()

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    zhangsan
    容器创建完成
    给容器中添加person....
    true
    
    5.@Conditional按照条件注册Bean

    新建Condition包,ZhangsanCondition类,实现Condition接口。matches()方法实现匹配逻辑:如果容器中已经包含id为"zhangsan"的bean,则注册当前bean;否则不注册。

    package com.ljessie.condition;
    
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.env.Environment;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class ZhangsanCondition implements Condition {
        /**
         *
         * @param context 判断条件使用的上下文环境
         * @param metadata 当前注释信息
         * @return
         */
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            //获取到IOC使用的beanFactory
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            //获取到类加载器
            ClassLoader classLoader = context.getClassLoader();
            //获取到环境
            Environment environment = context.getEnvironment();
            //获取到bean的注册类
            BeanDefinitionRegistry registry = context.getRegistry();
    
            //可以判断容器中的注册情况,也可以给容器中注册Bean
            //如果容器中包含"zhangsan",则注册;如果不包含,则不注册
            boolean containsZhangsan = registry.containsBeanDefinition("zhangsan");
            if(containsZhangsan){
                return true;
            }
    
    //        String property = environment.getProperty("os.name");
    //        if(property.contains("linux")){
    //            return true;
    //        }
    
            return false;
        }
    }
    

    MainConfig2里面添加person02()方法

        @Conditional({ZhangsanCondition.class})
        @Bean("zhangwu")
        public Person person02(){
            return new Person("zhangwu",27);
        }
    

    运行test02()

    @Test
        public void test02(){
            AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
            String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
            for (String name:beanDefinitionNames) {
                System.out.println(name);
            }
            System.out.println("容器创建完成");
    //        Person person1 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
    //        Person person2 = (Person) annotationConfigApplicationContext.getBean("zhangsan");
    //        System.out.println(person1 == person2);
        }
    

    运行结果,"zhangsan"和"zhangwu"都已经被注册到容器中了。

    给容器中添加person....
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    zhangsan
    zhangwu
    容器创建完成
    

    此时注掉MainConfig2里面的person()方法,重新运行test02()。此时"zhangsan"和"zhangwu"都没有被注册到容器中。

    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    容器创建完成
    
    6.使用@Import给容器中注册组件

    在bean包下,新建Color,Red

    package com.ljessie.bean;
    
    public class Color {
    }
    
    package com.ljessie.bean;
    
    public class Color {
    }
    

    在MainConfig2类上面添加@Import

    @Import({Color.class, Red.class})
    public class MainConfig2 {
    //省略其他代码
    }
    

    IOCTest里面新建testImport()方法

    AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
        @Test
        public void testImport(){
            printBeans(annotationConfigApplicationContext);
            //工厂bean获取的是:getObject()创建的对象
            //Object colorFactoryBean = annotationConfigApplicationContext.getBean("colorFactoryBean");
            //System.out.println(colorFactoryBean.getClass());
    
        }
    
        public void printBeans(AnnotationConfigApplicationContext annotationConfigApplicationContext){
            String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
            for (String name:beanDefinitionNames) {
                System.out.println(name);
            }
        }
    

    运行testImport():Color和Red都已经注册到容器中了。

    org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 10:49:33 CST 2020]; root of context hierarchy
    
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    com.ljessie.bean.Color
    com.ljessie.bean.Red
    

    使用ImportSelector注册组件
    新建Blue,Yellow类

    package com.ljessie.bean;
    
    public class Blue {
    }
    
    package com.ljessie.bean;
    
    public class Yellow {
    }
    

    新建MyImportSelector,实现ImportSelector方法

    package com.ljessie.condition;
    
    import org.springframework.context.annotation.ImportSelector;
    import org.springframework.core.type.AnnotationMetadata;
    
    /**
     * 自定义逻辑,返回需要导入的组件
     */
    public class MyImportSelector implements ImportSelector {
        /**
         *
         * @param importingClassMetadata 当前标注@Import注解的类的所有注册信息
         * @return 返回值就是导入容器中的组件的全类名,不要返回null
         */
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    
            return new String[]{"com.ljessie.bean.Blue","com.ljessie.bean.Yellow"};
        }
    }
    

    MainConfig2里面@Import添加MyImportSelector .class

    @Import({Color.class, Red.class, MyImportSelector.class})
    public class MainConfig2 {
    //省略其他代码
    }
    

    运行testImport():Blue和Yellow也注册进来了

    org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 10:56:22 CST 2020]; root of context hierarchy
    
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    com.ljessie.bean.Color
    com.ljessie.bean.Red
    com.ljessie.bean.Blue
    com.ljessie.bean.Yellow
    

    使用ImportBeanDefinitionRegistrar注册组件
    新建RainBow类

    package com.ljessie.bean;
    
    public class RainBow {
    }
    

    新建MyImportBeanDefinitionRegistrar,实现ImportBeanDefinitionRegistrar接口:如果容器中包含Red,则注册RainBow

    package com.ljessie.condition;
    
    import com.ljessie.bean.RainBow;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.RootBeanDefinition;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
        /**
         *
         * @param importingClassMetadata:当前类的注册信息
         * @param registry:BeanDefinition的注册类,所有要添加到容器中的bean
         */
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            boolean red = registry.containsBeanDefinition("com.ljessie.bean.Red");
            if(red){
                //指定Bean的定义信息
                RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
                //注册一个Bean
                registry.registerBeanDefinition("rainBow", rootBeanDefinition);
            }
        }
    }
    

    MainConfig2类上面,@Import注解添加MyImportBeanDefinitionRegistrar.class

    @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
    public class MainConfig2 {
    //省略其他代码
    }
    

    运行testImport()方法:rainBow注册进来了。

    org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 11:02:51 CST 2020]; root of context hierarchy
    
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    com.ljessie.bean.Color
    com.ljessie.bean.Red
    com.ljessie.bean.Blue
    com.ljessie.bean.Yellow
    rainBow
    
    7.使用FactoryBean给容器中注册组件

    新建ColorFactoryBean,实现FactoryBean接口

    package com.ljessie.bean;
    
    import org.springframework.beans.factory.FactoryBean;
    
    /**
     * 创建一个Spring提供的工厂Bean
     */
    public class ColorFactoryBean implements FactoryBean<Color> {
        /**
         *
         * @return Color对象,添加到容器中
         * @throws Exception
         */
        public Color getObject() throws Exception {
            System.out.println("ColorFactoryBean----->getObject()");
            return new Color();
        }
    
        public Class<?> getObjectType() {
            return Color.class;
        }
    
        public boolean isSingleton() {
            return true;
        }
    }
    

    在MainConfig2里面添加方法

    @Bean
        public ColorFactoryBean colorFactoryBean(){
            return new ColorFactoryBean();
        }
    

    修改testImport():

    @Test
        public void testImport(){
            printBeans(annotationConfigApplicationContext);
            //工厂bean获取的是:getObject()创建的对象
            Object colorFactoryBean = annotationConfigApplicationContext.getBean("colorFactoryBean");
            System.out.println(colorFactoryBean.getClass());
    
        }
    
        public void printBeans(AnnotationConfigApplicationContext annotationConfigApplicationContext){
            String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
            for (String name:beanDefinitionNames) {
                System.out.println(name);
            }
        }
    

    运行testImport(),拿到的colorFactoryBean实际是,getObject()方法里返回的Color类型。

    org.springframework.context.annotation.AnnotationConfigApplicationContext@67f89fa3: startup date [Sat Jan 18 11:09:11 CST 2020]; root of context hierarchy
    
    org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    org.springframework.context.annotation.internalRequiredAnnotationProcessor
    org.springframework.context.annotation.internalCommonAnnotationProcessor
    org.springframework.context.event.internalEventListenerProcessor
    org.springframework.context.event.internalEventListenerFactory
    mainConfig2
    com.ljessie.bean.Color
    com.ljessie.bean.Red
    com.ljessie.bean.Blue
    com.ljessie.bean.Yellow
    colorFactoryBean
    rainBow
    ColorFactoryBean----->getObject()
    class com.ljessie.bean.Color
    
    组件注册总结

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

    相关文章

      网友评论

          本文标题:Spring使用注解注册组件

          本文链接:https://www.haomeiwen.com/subject/tzdczctx.html