首页 > 其他分享 >@Import注解 -【Spring底层原理】

@Import注解 -【Spring底层原理】

时间:2024-08-30 11:25:20浏览次数:13  
标签:Spring class 注解 Import annotation public sourceClass

通过在配置类上使用@Import注解,将User给注入进容器中,运行启动类,可以看到容器中有User对象:

image-20210226164625069

image-20210226164625069

【2】导入ImportSelector的实现类

导入ImportSelector的实现类需要实现ImportSelector类,自定义逻辑返回需要导入的组件,返回的字符串数组即是要注入的组件,添加修改如下代码:

//?ImportSelector实现类

public?class?MyImportSelector?implements?ImportSelector?{

/**

*?@description?获取要导入到容器的组件全类名

*?@author?ONESTAR

*?@date?2021/2/25?15:49

*?@param?annotationMetadata:当前标注@Import注解类的所有注解信息

*?@throws

*?@return?java.lang.String[]

*/

public?String[]?selectImports(AnnotationMetadata?annotationMetadata)?{

return?new?String[]{"bean.Person"};

}

}

//?待注入的Person

public?class?Person?{

}

//?配置类

@Configuration

@Import({User.class,?MyImportSelector.class})?????//使用@Import导入组件,ID默认是组件的全类名

public?class?AppConfig?{

}

ImportSelector实现类中获取要导入到容器的组件全类名,这里将ImportSelector实现类在配置类中使用@Import注解进行配置,运行启动类,可以看到容器中有Person对象:

image-20210227151242060

image-20210227151242060

【3】导入ImportBeanDefinitionRegistrar的实现类

导入ImportBeanDefinitionRegistrar的实现类需要实现ImportBeanDefinitionRegistrar类,通过实现registerBeanDefinitions方法手动注册Bean到容器中,添加修改如下代码:

//?ImportBeanDefinitionRegistrar实现类

public?class?MyImportBeanDefinitionRegistrar?implements?ImportBeanDefinitionRegistrar?{

public?void?registerBeanDefinitions(AnnotationMetadata?annotationMetadata,?BeanDefinitionRegistry?beanDefinitionRegistry)?{

//?指定Bean的名称

RootBeanDefinition?beanDefinition?=?new?RootBeanDefinition(Animal.class);

beanDefinitionRegistry.registerBeanDefinition("Animal",?beanDefinition);

}

}

//?待注入的Animal

public?class?Animal?{

}

//?配置类

@Configuration

@Import({User.class,?MyImportSelector.class,?MyImportBeanDefinitionRegistrar.class})?????//使用@Import导入组件,ID默认是组件的全类名

public?class?AppConfig?{

}

通过ImportBeanDefinitionRegistrar的实现类进行手动注册添加Bean,并在配置类中使用@Import注解进行配置,运行启动类,可以看到容器中有Animal对象:

image-20210227153057676

image-20210227153057676

三、源码追踪

参考:https://blog.csdn.net/mamamalululu00000000/article/details/86711079

通过@Configuration注解,会进入到doProcessConfigurationClass方法,此时解析的是appConfigure,在doProcessConfigurationClass方法里面,有个执行@Import注解的方法,即processImports

this.processImports(configClass,?sourceClass,?this.getImports(sourceClass),?filter,?true);

@Import注解执行的时机,解析配置类的时候,由ConfigurationClassParser当中的processImports来处理,在分析processImports方法之前,咱们先来看看参数getImports方法:

【1】getImports方法

进入源码查看方法,这个方法就是获取所有的@import?里面的类,流程如下:

  1. 定义一个 visited 的集合,用作 是否已经 判断过的标志

  2. 这里就是获取sourceClass 上面的 所有的 annotation,并挨个判断, 如果不是 @import ,那就 进一步递归 调用 对应的 annotation,直到全部结束

  3. 加载sourceClass 里面 的@Import annotation 里面对应的类名 ,最后返回

//?获取所有的@import?里面的类

private?Set<ConfigurationClassParser.SourceClass>?getImports(ConfigurationClassParser.SourceClass?sourceClass)?throws?IOException?{

Set<ConfigurationClassParser.SourceClass>?imports?=?new?LinkedHashSet();

Set<ConfigurationClassParser.SourceClass>?visited?=?new?LinkedHashSet();

this.collectImports(sourceClass,?imports,?visited);

return?imports;

}

//?这里就是获取sourceClass?上面的?所有的?annotation,?如果不是?@import?,那就?进一步递归?调用?对应的?annotation,直到全部结束

private?void?collectImports(ConfigurationClassParser.SourceClass?sourceClass,?Set<ConfigurationClassParser.SourceClass>?imports,?Set<ConfigurationClassParser.SourceClass>?visited)?throws?IOException?{

if?(visited.add(sourceClass))?{

Iterator?var4?=?sourceClass.getAnnotations().iterator();

while(var4.hasNext())?{

ConfigurationClassParser.SourceClass?annotation?=?(ConfigurationClassParser.SourceClass)var4.next();

String?annName?=?annotation.getMetadata().getClassName();

if?(!annName.equals(Import.class.getName()))?{

this.collectImports(annotation,?imports,?visited);

}

}

imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(),?"value"));

}

}

标签:Spring,class,注解,Import,annotation,public,sourceClass
From: https://blog.51cto.com/u_15767217/11874830

相关文章

  • SpringBoot记录日志
    @Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public@interfaceLog{//自定义操作日志记录注解publicStringtitle();//模块名称publicOperatorTypeoperatorType()defaultOperatorType.MAN......
  • spring boot 根据实体类生成表
    在开发的过程中,经常会遇到数据库表结构发生变化或者新增表的情况,而spring体系下提供的springdatajpa可以帮助我们很方便的处理这种情况,只需要简单的配置既可!以下便是实现路径以及其中需要注意的事项。添加依赖<dependency><groupId>org.springframework.boo......
  • 基于SpringBoot的大学生就业需求分析系统设计与实现
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • Spring框架中如何实现国际化(i18n)?
    在Spring框架中实现国际化(i18n)主要涉及以下几个步骤:1.准备资源文件首先,你需要为不同语言准备资源文件。这些资源文件通常放在类路径下的特定目录中,如src/main/resources/下的messages.properties文件。对于不同的语言和地区,你可以创建对应的.properties文件,例如me......
  • Java后端微服务架构下的服务认证机制:Spring Security OAuth
    Java后端微服务架构下的服务认证机制:SpringSecurityOAuth大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在微服务架构中,服务之间的安全认证是一个复杂而重要的问题。SpringSecurityOAuth提供了一套强大的解决方案,通过它,我们可以轻松实现服务的认......
  • 记Spring HTTP Invoker远程调用的使用(二)基于Servlet方式,配置servlet映射url-pattern实
    目录前言一、概念二、代码实现1.服务端实现2.客户端实现前言本篇接上一篇记SpringHTTPInvoker远程调用的使用(一)基于Url映射方式,DispatcherServlet统一处理实现-CSDN博客https://blog.csdn.net/u011529483/article/details/141678510?spm=1001.2014.3001.5501之......
  • 二. Spring Boot 中的 “依赖管理和自动配置” 详解透彻到底(附+详细代码流程)
    二.SpringBoot中的“依赖管理和自动配置”详解透彻到底(附+详细代码流程)@目录二.SpringBoot中的“依赖管理和自动配置”详解透彻到底(附+详细代码流程)1.如何理解“约定优于配置”2.SpringBoot依赖管理和自动配置2.1SpringBoot的依赖管理2.1.1什么是依赖管理......
  • 如何使用Spring IOC的注解进行开发
    目录1、如何使用注解标记和扫描2、如何使用注解配置作用域和周期方法3、如何使用注解进行引用类型自动装配4、如何使用注解对基本类型属性赋值Spring IoC(Inversion of Control,控制反转)容器通过注解提供了一种简洁且强大的方式来进行依赖注入和配置管理。注解开发使得......
  • 逆向工程、Spring框架IOC、AOP学习
    系列文章目录第一章基础知识、数据类型学习第二章万年历项目第三章代码逻辑训练习题第四章方法、数组学习第五章图书管理系统项目第六章面向对象编程:封装、继承、多态学习第七章封装继承多态习题第八章常用类、包装类、异常处理机制学习第九章集合学习第......
  • 全栈程序员 | 精通安卓、鸿蒙,小程序,Java、Vue.js、SpringBoot及更多技术
    我是一个全栈程序员,擅长多种开发技术,包括安卓开发、Java编程、Vue.js、SpringBoot以及小程序开发等。我在技术上有广泛的涉猎,并致力于将创新解决方案应用于实际项目中。无论是开发高性能的安卓应用,还是构建响应式网页、实现复杂的后端功能,我都能提供专业的技术支持和高质量的代......