Spring中@Import原理和使用

@Import注解是Spring框架中一个非常强大的工具,它允许你将普通类、组件类、ImportSelector实现类和ImportBeanDefinitionRegistrar实现类引入到容器中。通过@Import,你可以实现配置的模块化,使得代码更加清晰和易于维护。

Spring集成很多框架时,就是通过@Import来实现的。

本文中源码来自Spring 5.3.x分支,github源码地址:GitHub - spring-projects/spring-framework: Spring Framework

一 如何使用@Import

该注解只有一个value属性,取值为需要导入的类的class对象。

有三种用法,介绍如下。

1.1 @Import导入普通类

对于普通类(没有被声明为Component),通过 @Import 也可以添加到Spring容器中

例如,使用@Import(OrderService.class) ,就能向容器中添加OrderService类型的bean

import com.xiakexing.service.OrderService;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Configuration
@Import(OrderService.class)
public class AppConfig {
}
// 没有使用@Component的普通类
public class OrderService {public void test() {System.out.println("执行OrderService.test");}
}
public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);OrderService orderService = context.getBean("orderService", OrderService.class);orderService.test();}
}

当执行上面代码时,会出现报错:No bean named 'orderService' available.

注意,通过@Import直接导入的bean,名称是该类的全类名。

因此应这样获取context.getBean(OrderService.class.getName(), OrderService.class)

1.2 @Import与ImportSelector 接口

ImportSelector接口,允许你自定义条件动态选择要导入的配置类,有两个方法:

  1. selectImports:返回一个全类名的数组,这些类将被添加到spring容器中。注意,该方法可以返回空数组,但是不能返回null!
  2. getExclusionFilter:返回一个Predicate,用于排除selectImports方法返回值中的某些类。

来看示例,OrderService与上面相同,增加UserService类。

public class UserService {public void test() {System.out.println("执行UserService.test");}
}

SimpleImportSelector只导入UserService类。

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;import java.util.function.Predicate;public class SimpleImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{OrderService.class.getName(), UserService.class.getName()};}// 排除全类名中有Order的类@Overridepublic Predicate<String> getExclusionFilter() {return new Predicate<String>() {@Overridepublic boolean test(String name) {return name.contains("Order");}};}
}
import com.xiakexing.service.SimpleImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Configuration
@Import(SimpleImportSelector.class)
public class AppConfig {
}
import com.xiakexing.service.OrderService;
import com.xiakexing.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class.getName(), UserService.class);userService.test();OrderService orderService = context.getBean(OrderService.class.getName(), OrderService.class);orderService.test();}
}

结果就是userService.test()执行成功,而获取orderService时报错。

1.3 @Import与 ImportBeanDefinitionRegistrar 接口

ImportBeanDefinitionRegistrar 接口允许通过编程方式动态注册BeanDefinition。

来看示例,定义User类。

public class User {private String name;private int age;public User() {}public User(String name, int age) {this.name = name;this.age = age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}

自定义ImportBeanDefinitionRegistrar 接口实现,编程式向容器中注册User类的beanDefinition,Spring容器将创建对应的bean。

import com.xiakexing.entity.User;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;public class SimpleBeanRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();definition.setBeanClass(User.class);ConstructorArgumentValues values = new ConstructorArgumentValues();values.addIndexedArgumentValue(0, "Tom");values.addIndexedArgumentValue(1, 29);definition.setConstructorArgumentValues(values);definition.setScope("singleton");registry.registerBeanDefinition("user", definition);}
}
import com.xiakexing.service.SimpleBeanRegistrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Configuration
@Import(SimpleBeanRegistrar.class)
public class AppConfig {
}

二 @Import的原理

Spring中ConfigurationClassPostProcessor类,会扫描所有的@Configuration类,并处理其中的@Import注解。

  1. 扫描配置类:Spring容器启动时,会扫描所有的@Configuration类。
  2. 解析@Import注解:对于每个配置类,Spring会解析其中的@Import注解,获取需要导入的类。
  3. 处理导入的类:根据导入的类的类型(普通类、@Configuration类、ImportSelector实现类、ImportBeanDefinitionRegistrar实现类),Spring会采取不同的处理方式。
  4. 注册BeanDefinition:最终,Spring会将所有导入的类注册为BeanDefinition,让Spring容器管理。

源码中ConfigurationClassParser类负责解析@Configuration类,其中doProcessConfigurationClass方法逻辑如下:

  1. 先递归地收集配置类或某个注解上的@Import的value值;

  2. 然后调用processImports方法来处理@Import注解,分3种情况处理导入的类。

  3. 例如,对于ImportBeanDefinitionRegistrar接口实现,先收集到Map中缓存起来,

    然后遍历Map,逐个调用registerBeanDefinitions方法

三 源码中使用

Spring源码中,模块化、插拔式的功能选项,就是通过@Import实现的。如aop、

3.1 @EnableAspectJAutoProxy实现

当在配置类上添加@EnableAspectJAutoProxy时,就启用了Spring aop功能。

源码中,EnableAspectJAutoProxy注解上通过Import引入了AspectJAutoProxyRegistrar,该类ImportBeanDefinitionRegistrar接口的实现,在registerBeanDefinitions方法中向容器注册了AnnotationAwareAspectJAutoProxyCreator。

AnnotationAwareAspectJAutoProxyCreator类是BeanPostProcessor接口的一个实现,会解析容器中@Aspect注解的bean,封装@Before等方法为Advisor对象;在bean的初始化后阶段,为切面命中的bean创建代理对象。

3.2 @EnableAsync实现

@EnableAsync注解提供了开箱即用的异步解决方案,我们只需在想要异步执行的方法上加@Async即可。

源码中,EnableAsync注解上通过Import引入了AsyncConfigurationSelector类,该类是ImportSelector接口实现,在selectImports方法中引入了ProxyAsyncConfiguration类(默认使用JDK动态代理)。

在ProxyAsyncConfiguration中,又声明了AsyncAnnotationBeanPostProcessor的bean。后者是BeanPostProcessor接口实现,在bean的初始化后阶段,为使用了@Async的bean创建代理对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/18591.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《pytorch》——优化器的解析和使用

优化器简介 在 PyTorch 中&#xff0c;优化器&#xff08;Optimizer&#xff09;是用于更新模型参数以最小化损失函数的关键组件。在机器学习和深度学习领域&#xff0c;优化器是一个至关重要的工具&#xff0c;主要用于在模型训练过程中更新模型的参数&#xff0c;其目标是最…

第J2周:ResNet50V2算法实战与解析

文章目录 一、准备工作1.设置GPU2.导入数据3.查看数据 二、数据预处理1.加载数据2.可视化数据 总结 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、准备工作 1.设置GPU import tensorflow as tf gpus …

CAS单点登录(第7版)18.日志和审计

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 日志和审计 Logging 概述 Logging CAS 提供了一个日志记录工具&#xff0c;用于记录重要信息事件&#xff0c;如身份验证成功和失败;可以对其进行自定义以生成用于故障排除的其他信息。…

Mybatisplus-IService

文章目录 简介IService如何继承基础业务完成复杂业务逻辑更简便的Lambda方法批处理 简介 IService类似于我们的BaseMapper吧 现在就是Service层的那些简单的CRUD也不用写了 下面是方法图 IService如何继承 不同于Mapper可以直接基础BaseMapper接口不用实现 我们的serviceIm…

一键安装教程

Maven 安装 右键 以管理员身份运行点击 下一步安装完成后会同步配置环境变量打开 cmd, 输入 mvn 查看mvn版本修改 maven 本地仓库地址 见图三, 本地新建文件夹&#xff0c;修改为你本地文件夹地址 Redis 安装 右键 以管理员身份运行点击 下一步会安装到选择的文件夹下 JAVA\R…

5分钟掌握LM Studio本地部署DeepSeek R1

文章目录 LM Studio安装与配置修改模型下载源下载DeepSeek R1模型模型选择配置模型部署API服务常见问题解决总结LM Studio安装与配置 下载地址:https://lmstudio.ai/ LM Studio 是一款专为开发者设计的轻量级集成开发环境(IDE),支持多种编程语言及框架,提供智能代码补全…

(前端基础)HTML(一)

前提 W3C:World Wide Web Consortium&#xff08;万维网联盟&#xff09; Web技术领域最权威和具有影响力的国际中立性技术标准机构 其中标准包括&#xff1a;机构化标准语言&#xff08;HTML、XML&#xff09; 表现标准语言&#xff08;CSS&#xff09; 行为标准&#xf…

Beszel监控Docker安装

一、Beszel Hub安装 #Beszel Hub安装 mkdir -p ./beszel_data && \ docker run -d \--name beszel \--restartunless-stopped \-v ./beszel_data:/beszel_data \-p 8090:8090 \henrygd/beszel#创建账号 账号/密码&#xff1a;adminadmin.com/adminadmin.com 二、Besz…

flutter image_cropper插件安装后 打包apk 报错命名空间问题

本篇文章主要讲解&#xff0c;Flutter安装完新依赖打包apk报错 A problem occurred configuring project ‘:image_cropper’. 命名空间问题的解决办法及原因说明。 日期&#xff1a;2025年2月15日 作者&#xff1a;任聪聪 一、报错现象&#xff1a; 报文信息&#xff1a; FAI…

unity学习41:动画里的曲线curve参数 和 事件 events

目录 1 曲线 curve 1.1 生成和修改曲线 1.2 曲线命名 animator参数命名&#xff0c;关联起来 1.3 可以修改animator的参数&#xff0c;也可以获取animator的参数 1.4 用脚本获得曲线的参数数值&#xff0c;并打印出来 1.4.1 获得曲线的test1参数 1.4.2 代码 1.4.3 测…

JVM学习

JVM 1、JVM是一个跨语言的平台&#xff0c;与语言无关 2、java虚拟机规范&#xff1a;一流企业做标准&#xff0c;二流企业做品牌&#xff0c;三流企业做产品 JVM种类 Hotspot&#xff1a;Oracle 公司&#xff0c;有商业版和免费版 open jdk 内部包含免费版本hotspot虚拟机 Jr…

DeepSeek 助力 Vue 开发:打造丝滑的开关切换(Switch)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

141,【1】buuctf web [SUCTF 2019]EasyWeb

进入靶场 代码审计 <?php // 定义函数get_the_flag&#xff0c;功能是处理文件上传相关操作 function get_the_flag() {// 注释说明&#xff1a;webadmin会每隔20分钟删除用户上传的文件$userdir "upload/tmp_" . md5($_SERVER[REMOTE_ADDR]);// 检查用户目录…

基于STM32的智能鱼塘养殖监控系统

1. 引言 水产养殖业正朝着智能化、精细化方向发展&#xff0c;传统养殖模式存在水质监控滞后、投喂不精准等问题。本文设计了一款基于STM32的智能鱼塘养殖监控系统&#xff0c;通过实时监测水质参数、自动投喂与远程管理&#xff0c;实现科学养殖&#xff0c;提高产量与经济效…

mapbox V3 新特性,添加下雪效果

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;mapbox 从入门到精通 文章目录 一、&#x1f340;前言1.1 ☘️mapboxgl.Map 地图对象…

Large Language Model Distilling Medication Recommendation Model

摘要&#xff1a;药物推荐是智能医疗系统的一个重要方面&#xff0c;因为它涉及根据患者的特定健康需求开具最合适的药物。不幸的是&#xff0c;目前使用的许多复杂模型往往忽视医疗数据的细微语义&#xff0c;而仅仅严重依赖于标识信息。此外&#xff0c;这些模型在处理首次就…

高血压危险因素分析(项目分享)

高血压危险因素分析&#xff08;项目分享&#xff09; 高血压作为一种极为常见的慢性疾病&#xff0c;正严重威胁着大众健康。它的发病机制较为复杂&#xff0c;涉及多个方面的因素。 在一份临床采集的数据的基础上&#xff0c;我们通过数据分析手段深入观察一下 BMI&#xf…

基于STM32的智能垃圾分类回收系统

1. 引言 随着城市化进程加快&#xff0c;传统垃圾处理方式已无法满足环保需求。本文设计了一款基于STM32的智能垃圾分类回收系统&#xff0c;通过图像识别、重量检测与自动分拣技术&#xff0c;实现垃圾精准分类&#xff0c;提高回收效率&#xff0c;助力城市可持续发展。 2. …

二、深入剖析线程安全性问题与底层原理

1.什么是线程安全&#xff1f;线程安全会带来哪些底层问题&#xff1f; 2.分析保证线程安全的三个性质-原子性、可见性、有序性 3.多场景剖析未保证原子性带来的问题 package imooc.atomic;public class AtomicTest {public static void main(String[] args) throws Interrupte…

IntelliJ IDEA 接入 AI 编程助手(Copilot、DeepSeek、GPT-4o Mini)

IntelliJ IDEA 接入 AI 编程助手&#xff08;Copilot、DeepSeek、GPT-4o Mini&#xff09; &#x1f4ca; 引言 近年来&#xff0c;AI 编程助手已成为开发者的高效工具&#xff0c;它们可以加速代码编写、优化代码结构&#xff0c;并提供智能提示。本文介绍如何在 IntelliJ I…