>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring:Java Web开发技术详解》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 21704 个阅读者 刷新本主题
 * 贴子主题:  Spring Framework 组件注册 之 @Import 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-05-07 02:35:24     消息  查看  搜索  好友  邮件  复制  引用

Spring Framework  组件注册 之 @Import

写在前面
向spring中注册组件或者叫javaBean是使用spring的功能的前提条件。而且spring也提供了很多种方式,让我们可以将普通的javaBean注册到spring容器中,比如前一篇文章Spring Framework 组件注册 之 @Component中写的利用

@Component

注解将普通的javaBean注册到容器中,本文说的

@Import

注解也是spring Framework提供的将普通javaBean注册到容器中,以及后续文章会说的

@Configuration

,

FactoryBean

等方式。

@Import 注册普通Bean

使用

@Import

注册一个普通Bean,只需要在

@Import

注解中指定待注册Bean的class即可


/**
* 使用Import注解,注册一个普通的Bean
*/

@Data
public class TestImport {
    private String id = "@Import";
}

  在spring启动引导类中,添加

@Import

注解


/**
* spring 容器启动引导类
*/

@Import(TestImport.class)
public class TestImportBootstrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(TestImportBootstrap.class);
        System.out.println("context id : " + applicationContext.getId());
        String[] beanNames = applicationContext.getBeanNamesForType(TestImport.class);
        System.out.println("Bean Name is : " + Arrays.toString(beanNames));
        TestImport bean = applicationContext.getBean(TestImport.class);
        System.out.println("TestImport bean : " + bean);
        applicationContext.close();
    }
}

  spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c
Bean Name is : [com.spring.study.ioc.register.TestImport]
TestImport bean : TestImport(id=@Import)
通过简单使用

@Import

注解,便可以将一个普通的javaBean注册到spring容器中。并且我们可以看到,通过

@Import

注解默认注册的组件名称为该javaBean的全类名

@Import 导入 配置类

使用

@Import

注解导入配置类,就会将配置类中的所有组件注册到spring容器中。在spring中,并不是

@Configuration

标注的类才是配置类,但是被

@Configuration

标注的类会被生成代理对象,spring注入时与不使用

@Configuration

注解有很大区别,后续会单独说明此处内容,本文不在赘述。


/**
* spring组件配置类
*/

//@Configuration 使用@Import导入时,此注解可以不加
public class TestConfiguration {
    @Bean
    public TestImport testImport() {
        return new TestImport();
    }

    @Bean
    public TestImport testImport2() {
        return new TestImport();
    }
}

@Import

注解中指定待导入的配置类


/**
* spring 容器启动引导类
*/

@Import(TestConfiguration.class)
public class TestImportBootstrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(TestImportBootstrap.class);
        System.out.println("context id : " + applicationContext.getId());
        String[] beanNames = applicationContext.getBeanNamesForType(TestImport.class);
        System.out.println("Bean Name is : " + Arrays.toString(beanNames));
        TestImport bean = (TestImport) applicationContext.getBean("testImport");
        System.out.println("TestImport bean : " + bean);
        applicationContext.close();
    }
}

  spring容器启动后,配置类中的注解同样会被注册到spring容器中:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c
Bean Name is : [testImport, testImport2]
TestImport bean : TestImport(id=@Import)
由结果可以看出,此时注册的组件名称即为配置类中指定的组件名称,并且通过配置类,可以一次导入多个组件。

@Import 通过ImportSelector 注册



ImportSelector

接口中只定义了一个接口

selectImports

,通过此接口返回需要注册的JavaBean的全类名数组,在使用

@Import

导入时,会将接口返回的所有类注册到spring容器中


/**
* 通过 ImportSelector 接口注册组件
*/

@Data
public class TestSelector {
    private String id = "@Import:ImportSelector";
}

  自定义实现

ImportSelector

接口


/**
* 自定义组件选择器,通过返回需要注册的bean的全类名,进行快速的在IOC容器中注册组件
*/

public class CustomImportSelector implements ImportSelector {

    /**
     * @param importingClassMetadata 标注了@Import配置类上面所有的注解信息
     */

    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{TestSelector.class.getName()};
    }
}

@Import

注解中指定ImportSelector实现类


/**
* spring 容器启动引导类
*/

@Import(CustomImportSelector.class)
public class TestImportBootstrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(TestImportBootstrap.class);
        System.out.println("context id : " + applicationContext.getId());
        TestSelector bean = applicationContext.getBean(TestSelector.class);
        System.out.println("TestSelector bean : " + bean);
        String[] beanNames = applicationContext.getBeanNamesForType(TestSelector.class);
        System.out.println("bean names:" + Arrays.asList(beanNames));
        applicationContext.close();
    }
}

  spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@238e0d81
TestSelector bean : TestSelector(id=@Import:ImportSelector)
bean names:[com.spring.study.ioc.register.TestSelector]
由结果可以看出,

TestSelector

被注册到了spring容器中。与前面的直接注册相比,并没有看出

ImportSelector

接口的突出特性。本文只是简单的说明

ImportSelector

接口具有注册组件的功能,对于spring容器在启动时,如何执行

BeanDefinitionRegistryPostProcessor

来调用

selectImports

方法;如何使用

ImportSelector

接口实现更复杂的注册功能,将在后续文章中深入理解。

@Import 通过ImportBeanDefinitionRegistrar 注册



ImportBeanDefinitionRegistrar

接口中只定义了一个

registerBeanDefinitions

方法,在此方法中,可以获取到

BeanDefinitionRegistry

对象,利用此对象,即可手动将需要的组件注册的spring容器中。在使用

BeanDefinitionRegistry

对象时,还可以指定组件在spring容器中注册的bean名称。


/**
* 通过 ImportBeanDefinitionRegistrar 接口手动注册组件
*/

@Data
public class TestRegistrar {
    private String id = "@Import:TestRegistrar";
}

  自定义实现

ImportBeanDefinitionRegistrar

接口


/**
* 手动注册组件到IOC容器中
*/

public class CustomImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    /**
     * @param importingClassMetadata 标注了@Import配置类上面所有的注解信息
     * @param registry               BeanDefinition注册器,可以通过此registry手动的向容器中注册指定的组件
     */

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        if (!registry.containsBeanDefinition("testRegistrar")) {
            BeanDefinition definition = new RootBeanDefinition(TestRegistrar.class);
            registry.registerBeanDefinition("testRegistrar", definition);
        }
    }
}

@Import

注解中指定ImportBeanDefinitionRegistrar实现类


/**
* spring 容器启动引导类
*/

@Import(CustomImportBeanDefinitionRegistrar.class)
public class TestImportBootstrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(TestImportBootstrap.class);
        System.out.println("context id : " + applicationContext.getId());
        TestRegistrar bean = applicationContext.getBean(TestRegistrar.class);
        System.out.println("TestRegistrar bean : " + bean);
        String[] beanNames = applicationContext.getBeanNamesForType(TestSelector.class);
        System.out.println("bean names:" + Arrays.asList(beanNames));
        applicationContext.close();
    }
}

  spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@238e0d81
TestRegistrar bean : TestRegistrar(id=@Import:TestRegistrar)
bean names:[testRegistrar]
由此可以看出,

TestRegistrar

被注册到了spring容器中。与

ImportSelector

接口一样,在spring容器启动时,通过

BeanDefinitionRegistryPostProcessor

来执行接口方法。

@Import同时指定多种接口注册

上面的例子中分别说明了使用

@Import

,通过直接导入Bean class,配置类,

ImportSelector

接口,

ImportBeanDefinitionRegistrar

接口来向spring容器中注册组件。当然在使用

@Import

注解时,可以同时指定上面的任意几种方式进行注册


/**
* spring 容器启动引导类
*
* @author TangFD
* @since 2019/6/25.
*/

@Import({
        TestComponent.class,
        TestConfiguration.class,
        CustomImportSelector.class,
        CustomImportBeanDefinitionRegistrar.class
})
public class TestImportBootstrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(TestImportBootstrap.class);
        System.out.println("context id : " + applicationContext.getId());
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        System.out.println("bean names:" + Arrays.asList(beanNames));
        applicationContext.close();
    }
}

  spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@238e0d81
bean names:[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, testImportBootstrap, com.spring.study.ioc.register.TestComponent, com.spring.study.ioc.register.TestConfiguration, testImport, testImport2, com.spring.study.ioc.register.TestSelector, testRegistrar]

总结

向spring容器中注册组件的方式有很多,本文主要说明了如何使用

@Import

注解向spring容器中注册组件。并且遗留了一个需要深入理解的知识点:在spring容器启动时,如何通过执行

BeanDefinitionRegistryPostProcessor

来执行

ImportSelector



ImportBeanDefinitionRegistrar

接口方法进行组件注册。此处内容,将在后续的spring容器启动过程中,分析

BeanFactoryPostProcessor

接口执行过程里进行补充。

学习永远都不是一件简单的事情,可以有迷茫,可以懒惰,但是前进的脚步永远都不能停止。

不积跬步,无以至千里;不积小流,无以成江海;



----------------------------
原文链接:https://blog.51cto.com/8950379/2416136


程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->数据类型
  JavaWeb开发-->访问数据库(Ⅰ)
  JSP与Hibernate开发-->域对象在持久化层的四种状态
  Java网络编程-->ServerSocket用法详解
  精通Spring-->Vue简介
  Vue3开发-->虚拟DOM和render()函数
  Spring Boot 入门,用 Spring Boot 写第一个 HelloWorld 程序
  Redis为什么单线程能够支持高并发
  RocketMQ 常用消息类型
  git 常用指令总结
  MyBatis+Spring 事务管理
  如何编写优雅的Spring架构API
  SpringMVC下的JUnit4单元测试
  HandlerInterceptor与WebRequestInterceptor的异同
  Spring MVC控制器类的方法的所支持的方法参数类型
  什么是Redis?Redis的各项功能解决了哪些问题?
  Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)...
  SpringBoot构建Restful接口
  写给新手的Spring Cloud的微服务入门教程
  网红框架SpringBoot2.x之定制参数浅析
  Spring入门基础知识
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。