组件注册 07 @Import 给容器快速导入一个组件
给容器注册组件:
- 包扫描 + 组件标注注解(@Controller @Service @Repository @Component),局限于自己写的
- @Bean(可导入第三方包里的组件)
- @Import(快速给容器中导入组件)
- @Import([要导入容器中的组件]):容器中就会自动注册这个组件,id默认为全类名
@Import(Color.class)
@Import({Color.class,Red.class})
- 实现ImportSelector接口:返回需要导入的组件的全类名数组
- 实现ImportBeanDefinitionRegistrar接口:手动注册bean到容器中
- 使用Spring提供的FactoryBean工厂
配置类 MainConfig3.class
测试
@Test
void importTest(){
//配置类测试
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig3.class);
System.out.println("容器创建完毕");
System.out.println("准备获取bean...");
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String name:beanDefinitionNames){
System.out.println(name);
}
}
ImportSelector 测试
Color.java
package com.example.annotations.bean;
public class Color {
}
Red.java
package com.example.annotations.bean;
public class Red {
}
MyImportSelector.java
package com.example.annotations.importselector;
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) {
// 不能返回 null 可以是空数组
return new String[]{"com.example.annotations.bean.Color","com.example.annotations.bean.Red"};
}
}
运行结果:
实现ImportBeanDefinitionRegistrar接口
MyImportBeanDefinitionRegistrar.class
package com.example.annotations.importselector;
import com.example.annotations.bean.RainBow;
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;
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 当前类的注解信息
* @param registry BeanDefinition的注册类 负责将bean添加进容器
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 指定bean定义信息(Bean的类型 Bean的作用域 ...)
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
// 注册:指定bean名
if (!registry.containsBeanDefinition("rainbow")){
System.out.println(" start create 'rainbow' ...");
registry.registerBeanDefinition("rainbow",rootBeanDefinition);
}else {
System.out.println("'rainbow' already exists ");
}
}
}
运行结果
使用FatoryBean
普通bean
将bean导入到容器后,容器会调用其无参构造器,默认创建一个对象注册在容器中
FactoryBean
- 是一个接口
- 整合第三方框架的时候用的多
- 默认获取的是工厂bean调用getObject创建的对象
- 要获取工厂bean本身,需要给id前加一个
&
需要实现方法
getObject()
getObjectType()
isSingleton() :默认是true 单实例
实例测试
ColorFactoryBean.java
package com.example.annotations.bean;
import org.springframework.beans.factory.FactoryBean;
/**
* 创建一个Spring定义的FactoryBean
*/
public class ColorFactoryBean implements FactoryBean<Color> {
/**
* 返回分Color对象会被添加到容器中
* @return Color
* @throws Exception
*/
@Override
public Color getObject() throws Exception {
return new Color();
}
/**
*
* @return
*/
@Override
public Class<?> getObjectType() {
return Color.class;
}
/**
* true: 单实例 在容器中保存一份
* false:多实例 每获取一次就会创建一个新bean
* @return
*/
@Override
public boolean isSingleton() {
return true;
}
}
MainConfig2.java
@Configuration
public class MainConfig2 {
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
}
测试
@Test
void factoryBeanTest(){
//配置类测试
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
System.out.println("容器创建完毕");
System.out.println("准备获取bean...");
Object bean1 = applicationContext.getBean("colorFactoryBean");//Color.class
Object bean2 = applicationContext.getBean("colorFactoryBean");//Color.class
System.out.println("bean1 == bean2? => " + (bean1 == bean2));
}
测试结果
现将ColorFactoryBean.java中的isSingleton改为false,再次运行
查看获取的类型
@Test
void factoryBeanTest(){
//配置类测试
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
System.out.println("容器创建完毕");
System.out.println("准备获取bean...");
Object bean1 = applicationContext.getBean("colorFactoryBean");//Color.class 获取的是工厂bean调用
Object bean2 = applicationContext.getBean("&colorFactoryBean");//ColorFactoryBean.class
System.out.println("bean1 == bean2? => " + (bean1 == bean2));
System.out.println("bean1 " + bean1.getClass());
System.out.println("bean2 " + bean2.getClass());
}