@Import-给容器中导入组件
文章目录
英文学习:
- definition : 定义
给容器中添加组件:
- 包扫描 + 组件标注注解(@Controller, @Service, @Repository, @Component)
- 只能导入自己写的类
- @Bean注解导入
- 可以导入自己写的类, 也可以导入第三方包里面的组件
- @Import快速的给容器中导入一个组件
- 如果使用第二种方式导入一个第三方包中的组件会比较麻烦, 使用@Import方式会比较简单
@Import注解源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
@Import基础用法: 给容器中快速导入一个组件
1.创建一个实体类
package com.ffyc.spring.model;
public class Red {
}
2.创建一个配置类, 在配置类上使用@Import注解导入实体类
package com.ffyc.spring.config;
import com.ffyc.spring.condition.LinuxCondition;
import com.ffyc.spring.condition.WindowsCondition;
import com.ffyc.spring.controller.MyTypeFilter;
import com.ffyc.spring.model.Person;
import com.ffyc.spring.model.Red;
import org.springframework.context.annotation.*;
import javax.swing.*;
@Configuration
@ComponentScan(value = "com.ffyc.spring")
@Import(Red.class)
public class PersonConfig {
}
3.测试:
package com.ffyc.spring.test;
import com.ffyc.spring.config.PersonConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test5 {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(PersonConfig.class);
String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
for(String name : beanDefinitionNames) {
System.out.println(name);
}
}
}
可以看到确实是将我们的Red实体类对象注册(创建)到了IOC容器中
使用@Import(“要导入到容器中的组件”)的方式, 容器中就会自动注册这个组件, id默认是全类名
@Import高级 : 使用ImportSelector
1. 创建实体类:
package com.ffyc.spring.model;
public class Black {
}
package com.ffyc.spring.model;
public class Color {
}
2. 创建一个MyImportSelector(实现ImportSelector接口)
- 要重写其中的selectImports()抽象方法
package com.ffyc.spring.condition;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {"com.ffyc.spring.model.Color", "com.ffyc.spring.model.black"};
}
}
selectImports()方法最终会返回一个String[], 该String[]中的内容就是要注册到IOC容器中的类的全类名
AnnotationMetadata : 当前标注@Import注解的类的所有注解信息
3.创建一个配置类, 使用@Import注解
package com.ffyc.spring.config;
import com.ffyc.spring.condition.LinuxCondition;
import com.ffyc.spring.condition.MyImportSelector;
import com.ffyc.spring.condition.WindowsCondition;
import com.ffyc.spring.controller.MyTypeFilter;
import com.ffyc.spring.model.Person;
import com.ffyc.spring.model.Red;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan(value = "com.ffyc.spring")
@Import({Red.class, MyImportSelector.class})
public class PersonConfig {
}
一定要注意: @Import({Red.class, MyImportSelector.class}), 对于第一个Red.class, 确实表示的是要加载Red.class类型的实例到IOC容器中
但是第二个却不是表示要加载MyImportSelector.class类型的实例到IOC容器中, 因为此时的MyImportSelector类实现了ImportSelector接口, 这是一种@Import注解的高级用法, 底层会通过反射的方式调用其中的selectImports()方法获取到对应的返回值作为要导入的Bean实例
@Import高级 : 使用@ImportBeanDefinitionRegister
1. 创建实体类:
package com.ffyc.spring.model;
public class RainBow {
}
2.创建MyImportBeanDefinitionRegister类实现ImportBeanDefinitionRegister接口
package com.ffyc.spring.condition;
import com.ffyc.spring.model.RainBow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean b = registry.containsBeanDefinition("com.ffyc.spring.model.Red");
boolean b1 = registry.containsBeanDefinition("com.ffyc.spring.model.Black");
if(b && b1) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
registry.registerBeanDefinition("rainBow", rootBeanDefinition);
}
}
}
重写registerBeanDefinitions()方法
AnnotationMetadata : 当前类的注解信息
BeanDefinitionRegistry : BeanDefinition注册类
把所有需要添加到IOC容器中的bean, 调用beanDefinitionRegistry.registerBeanDefinition手工注册进来
创建的RootBeanDefinition对象表示Bean定义信息(Bean的类型, Bean的作用域等等)
调用registerBeanDefinition()方法的时候的第一个参数是给bean起名, 也就是bean的id值
- 前两种方式的时候bean的id值都是默认的全类名, 但是对于这种方式中我们可以指定bean的id值
3.创建一个配置类, 使用@Import
package com.ffyc.spring.config;
import com.ffyc.spring.condition.LinuxCondition;
import com.ffyc.spring.condition.MyImportBeanDefinitionRegister;
import com.ffyc.spring.condition.MyImportSelector;
import com.ffyc.spring.condition.WindowsCondition;
import com.ffyc.spring.controller.MyTypeFilter;
import com.ffyc.spring.model.Person;
import com.ffyc.spring.model.Red;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan(value = "com.ffyc.spring")
@Import({Red.class, MyImportSelector.class, MyImportBeanDefinitionRegister.class})
public class PersonConfig {
}