spring常用注解@Import

本文深入解析Spring框架中@Import注解的功能与应用,探讨其如何将不同类型的组件注册到Spring容器,包括@Configuration类、ImportSelector、ImportBeanDefinitionRegistrar及普通bean的注册方式。

1.先来看下@Import的官方文档解释
在这里插入图片描述

解释下意思:
1.该类主要是为了将组件注册到容器中
2.注解里面value值可以有四种类型,通过引入这四种类型的数组,来注册进容器,分别为Configuration, ImportSelector, ImportBeanDefinitionRegistrar or regular component ,其中Configuration为引入有@Configuration注解的类,ImportSelector,ImportBeanDefinitionRegistrar 为对应接口的实现类,regular component就是普通的实体bean

1.Configuration

 通俗点理解就是可以通过此注解导入多个配置类,spring早期使用xml进行配置的时候,可以通过如下引入多个配置文件,这里就是这种用处,目前用得不多,就不赘述,反正不外乎注解里面加上有注解@Configuration的类
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xsi:schemaLocation="  
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
       ">  
        <import resource="classpath:META-INF/db.xml" />
		<import resource="classpath:META-INF/huatuo-db.xml" />
		<import resource="classpath:META-INF/db-mapper.xml" />
		<import resource="classpath:META-INF/huatuo-db-mapper.xml" />
		<import resource="classpath:META-INF/webservice.xml" />
		<import resource="classpath:META-INF/dubbo.xml" />
		<import resource="classpath:META-INF/spring/physicalExamService.xml" />
</beans> 

2.ImportSelector

先查看下该注解

在这里插入图片描述
目前此类就一个方法,方法的返回值为类名全路径的数组
举例:

package com.atguigu.condition;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {

	//返回值,就是到导入到容器中的组件全类名
	//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		// TODO Auto-generated method stub
		//importingClassMetadata
		//方法不要返回null值
		return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
	}

}

3.ImportBeanDefinitionRegistrar

先来看下此接口的注释信息
在这里插入图片描述
目前此接口只有一个方法,返回值为空,参数有该类的所有注解的信息,spring容器的注册器
实例:

package com.atguigu.condition;

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;

import com.atguigu.bean.RainBow;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * AnnotationMetadata:当前类的注解信息
	 * BeanDefinitionRegistry:BeanDefinition注册类;
	 * 		把所有需要添加到容器中的bean;调用
	 * 		BeanDefinitionRegistry.registerBeanDefinition手工注册进来
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		
		boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
		boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
		if(definition && definition2){
			//指定Bean定义信息;(Bean的类型,Bean。。。)
			RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
			//注册一个Bean,指定bean名
			registry.registerBeanDefinition("rainBow", beanDefinition);
		}
	}

}

4.regular component

这个就是普通的bean类了
实例

package com.atguigu.bean;

public class Color {
	
	private Car car;

	public Car getCar() {
		return car;
	}

	public void setCar(Car car) {
		this.car = car;
	}

	@Override
	public String toString() {
		return "Color [car=" + car + "]";
	}
}

好了,现在可以试下,有没有注册进容器
配置类

@Configuration
@Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
//@Import导入组件,id默认是组件的全类名
public class MainConfig2 {
	
	
//	@Scope("prototype")
	@Lazy
	@Bean("person")
	public Person person(){
		System.out.println("给容器中添加Person....");
		return new Person("张三", 25);
	}
}

public class IOCTest {
	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
	
	
	@Test
	public void testImport(){
		printBeans(applicationContext);
		Blue bean = applicationContext.getBean(Blue.class);
		System.out.println(bean);
		
		//工厂Bean获取的是调用getObject创建的对象
		Object bean2 = applicationContext.getBean("colorFactoryBean");
		Object bean3 = applicationContext.getBean("colorFactoryBean");
		System.out.println("bean的类型:"+bean2.getClass());
		System.out.println(bean2 == bean3);
		
		Object bean4 = applicationContext.getBean("&colorFactoryBean");
		System.out.println(bean4.getClass());
	}
	
	private void printBeans(AnnotationConfigApplicationContext applicationContext){
		String[] definitionNames = applicationContext.getBeanDefinitionNames();
		for (String name : definitionNames) {
			System.out.println(name);
		}
	}
}

都注册成功
在这里插入图片描述

<think>我们被要求详细解释Spring框架中的@Import注解。根据提供的引用内容,我们可以总结如下: 引用[1]和[2]指出,@Import注解用于导入配置类,实现配置的模块化。它可以将一个或多个配置类引入到当前配置类中,类似于Spring XML配置文件中的`<import>`标签。@Import有三种使用方式:普通方式、ImportSelector方式、ImportBeanDefinitionRegistrar方式。 引用[4]展示了第一种方式:直接引入Bean。在配置类上使用@Import(ImportedBean.class),就可以将ImportedBean注册到Spring容器中。 此外,引用[3]提到了在处理@Import注解时,会通过beanDefinition的元数据(metadata)来获取类的注解信息,进而处理@Import注解中的内容。 因此,我们需要详细解释@Import注解的三种用法,并给出相应的示例。 ### 详细解释 #### 1. 普通方式 直接导入一个或多个配置类或普通类(这些类会被注册为Bean)。语法:`@Import({类1.class, 类2.class, ...})` 示例: ```java public class MyService {} @Configuration @Import(MyService.class) public class AppConfig {} ``` 这样,MyService就会被注册为一个Spring Bean。 #### 2. ImportSelector方式 通过实现`ImportSelector`接口,可以编程式地选择要导入的配置类。该接口有一个方法`String[] selectImports(AnnotationMetadata importingClassMetadata)`,返回要导入的类的全限定名的数组。 示例: ```java public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 根据条件返回需要导入的类 return new String[]{"com.example.ServiceA", "com.example.ServiceB"}; } } @Configuration @Import(MyImportSelector.class) public class AppConfig {} ``` #### 3. ImportBeanDefinitionRegistrar方式 通过实现`ImportBeanDefinitionRegistrar`接口,可以编程式地注册Bean定义。该接口有一个方法`void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)`,可以在其中使用BeanDefinitionRegistry来注册Bean。 示例: ```java public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 创建Bean定义 RootBeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class); // 注册Bean定义 registry.registerBeanDefinition("myBean", beanDefinition); } } @Configuration @Import(MyBeanDefinitionRegistrar.class) public class AppConfig {} ``` ### 总结 @Import注解Spring中用于模块化配置的重要注解,它提供了三种不同的方式来导入配置或Bean: 1. 直接导入类(普通方式) 2. 通过ImportSelector接口动态选择导入的类 3. 通过ImportBeanDefinitionRegistrar接口编程式注册Bean定义 使用@Import注解可以避免使用XML配置来组合配置,使得配置更加灵活和模块化。 ### 相关问题 1. @Import注解和@ComponentScan注解有什么区别? 2. 如何在使用@Import导入的配置类中使用@Autowired注入其他Bean? 3. 在Spring Boot中,@Import注解常用在哪些场景? </think>### Spring @Import 注解详细解释 `@Import` 是 Spring 框架的核心注解之一,用于**动态注册 Bean 到 IoC 容器**,实现配置的模块化。它有三种使用方式,每种方式对应不同的场景需求: #### 方式一:直接导入类(普通方式) - **作用**:将指定类注册为 Spring Bean - **语法**:`@Import(ClassName.class)` - **示例**: ```java public class DatabaseService {} // 待注册的类 @Configuration @Import(DatabaseService.class) // 直接导入 public class AppConfig {} ``` - **特点**: - 适用于简单场景 - 被导入的类无需额外注解(如 `@Component`) - 通过 `ApplicationContext.getBean(DatabaseService.class)` 可直接获取[^4] #### 方式二:实现 `ImportSelector` 接口 - **作用**:**动态选择**需要注册的 Bean - **核心方法**: ```java public interface ImportSelector { String[] selectImports(AnnotationMetadata importingClassMetadata); } ``` - **示例**: ```java public class DynamicImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata metadata) { // 根据条件动态返回类名 if (isProduction()) { return new String[]{ProdDataSource.class.getName()}; } return new String[]{DevDataSource.class.getName()}; } } @Configuration @Import(DynamicImportSelector.class) public class EnvConfig {} ``` - **特点**: - 实现条件化 Bean 注册 - 可读取导入类的元数据(`AnnotationMetadata`) - Spring Boot 的 `@EnableAutoConfiguration` 底层采用此机制[^2] #### 方式三:实现 `ImportBeanDefinitionRegistrar` 接口 - **作用**:**编程式注册 Bean 定义**(最灵活的方式) - **核心方法**: ```java public interface ImportBeanDefinitionRegistrar { void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry ); } ``` - **示例**: ```java public class CustomBeanRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { // 创建 Bean 定义 BeanDefinition definition = new RootBeanDefinition(CustomService.class); // 手动注册 Bean registry.registerBeanDefinition("customService", definition); } } @Configuration @Import(CustomBeanRegistrar.class) public class CustomConfig {} ``` - **特点**: - 完全控制 Bean 的注册过程 - 可访问 `BeanDefinitionRegistry` 进行高级操作 - 支持解析被导入类的元数据(如注解信息)[^3] --- ### 核心机制 1. **处理时机**:在容器启动时,Spring 解析 `@Import` 注解: - 检查 `BeanDefinition` 的元数据 (`getMetadata()`)[^3] - 递归处理所有导入的类或接口 2. **与 XML 等效操作**:等同于 XML 配置中的 `<import>` 标签: ```xml <!-- XML 等效配置 --> <import resource="database-config.xml"/> ``` 3. **模块化优势**: - 解耦大型项目配置 - 实现按需加载(如根据 Profile 加载不同配置) - 支持第三方库的无侵入整合(常见Spring Boot Starter) > 提示:三种方式可组合使用,例如 `@Import({ClassA.class, SelectorB.class})`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值