Spring注解学习之:@Import

本文详细介绍了Spring中四种Bean注册方法,重点讲解了@Import注解的使用,包括直接导入类、ImportSelector选择器和ImportBeanDefinitionRegistrar注册器。同时,还探讨了BeanFactory作为注册方式,通过实现FactoryBean来定制Bean信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,Spring往IOC容器中注册Bean的方法有以下几种:

1、通过包扫描+注解的方式;如@Controller,@Service,@Reposity,@Component;

2、通过@Bean的形式;

3、通过@Import的形式;

4、通过BeanFactory的形式进行注册;

前2点在上面的有所记录过,今天就主要记录一下在学习如何使用@Import和BeanFactory进行组件注册;首先看一下@Import;

一、@Import

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

	/**
	 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
	 * or regular component classes to import.
	 */
	Class<?>[] value();

}

首先可以看到@Improt需要传入一个泛型数组,也就是说@Import({XXX.class,BBBB.class});其次,还有2个注意的地方,一个叫做ImportSelector(选择器)和ImportBeanDefinitionRegistrar(Bean定义注册器)。ImportSelector和ImportBeanDefinitionRegistrar都是两个接口;换句话说就是@Import可以使用自定义组件注入,也可以使用实现ImportSelector或者是ImportBeanDefinitionRegistrar的方式进行注入;

(1)、@Import({XXX.class,BBBB.class})的方式

定义一个Animal类,Dog类,Pig类。然后通过@Import({XXX.class,BBBB.class})的方式,进行注入,上代码;

MyConfig.class

@Configuration
@Import({Dog.class,Person.class})
public class Myconfig {
}

--------------------------------------
测试类代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {

    @Test
    public void contextLoads() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

}

结果如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myconfig
com.snail.tool.bean.Dog
com.snail.tool.bean.Person

可以看到,Dog和Person都有进入到IOC容器中,这里有一点需要注意到,就是通过@Import注入的Bean,它的id默认是全类名;

(2)、ImportSelector选择器情况

首先ImportSelector是一个接口,需要进行实现改接口,新建一个AnimalImportSelector 类,实现ImportSelector接口,如下代码:

public class AnimalImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.snail.tool.bean.Pig","com.snail.tool.bean.Cat"};
    }
}

注意:
1、AnnotationMetadata 就是标注了@Import的当前类,可以通过该参数,拿出当前类的一些属性;
2、selectImports方法,返回的是一个数组;
3、@Import方式注入的Bean,id默认是全类名;如果不是全类名,会报错上下文无法找到;

运行结果:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myconfig
com.snail.tool.bean.Dog
com.snail.tool.bean.Person
com.snail.tool.bean.Pig
com.snail.tool.bean.Cat


可以看到,com.snail.tool.bean.Pig和com.snail.tool.bean.Cat已经在IOC容器中了

(3)、ImportBeanDefinitionRegistrar;同样的,这也是一个借口,先一个PersonImportBeanDefinitionRegistrar类来实现它,代码如下:


public class PersonImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        
    }
}

注意:
1、AnnotationMetadata:还是被@Import注解的当前类,可以通过该参数,拿到当前类的一些属性;
2、BeanDefinitionRegistry:Bean定义注册器,是一个接口,接口中过的方法如下:
    void registerBeanDefinition(String var1, BeanDefinition var2) ;

    void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    boolean containsBeanDefinition(String var1);

    String[] getBeanDefinitionNames();

    int getBeanDefinitionCount();

    boolean isBeanNameInUse(String var1);
    
    主要用到的是registerBeanDefinition这个方法,这个方法中,有一个BeanDefinition,用于定义作用域等属性,var1是Bean的id可以自定义;
MyConfig.class

@Configuration
@Import({Dog.class,Person.class,AnimalImportSelector.class,PersonImportBeanDefinitionRegistrar.class})
public class Myconfig {
}

---------------------------------
测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {

    @Test
    public void contextLoads() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

}

运行结果:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myconfig
com.snail.tool.bean.Dog
com.snail.tool.bean.Person
com.snail.tool.bean.Pig
com.snail.tool.bean.Cat
Student


可以看到,Student是被注册进来的;

springboot源码中,大量使用的都是@ImportSelector进行组件注入;通过ImportBeanDefinitionRegistrar,可以让开发者自定义组件信息;

二、BeanFactory,Bean工厂类;通过实现FactoryBean<T>的方法,进行Bean的设定,其中T代表泛型;这里创建一个类型为Teacher的PersonBeanFactory类;


public class PersonBeanFactory implements FactoryBean<Teacher> {

    //返回bean对象
    @Override
    public Teacher getObject() throws Exception {
        return new Teacher();
    }

    //返回bean的类型
    @Override
    public Class<?> getObjectType() {
        return Teacher.class;
    }

    //设置作用于范围
    @Override
    public boolean isSingleton() {
        return false;
    }
}

然后在配置类中进行配置,测试类中进行测试,代码如下:

Myconfig.class
@Configuration
public class Myconfig {

    @Bean
    public PersonBeanFactory personBeanFactory(){
        return new PersonBeanFactory();
    }
}

-------------------------------------
测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {

    @Test
    public void contextLoads() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

}

运行结果:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myconfig
personBeanFactory


可以看到有一个叫做personBeanFactory的Bean。

我们的BeanFactory是泛型指定,那看看personBeanFactory这个Bean的类型是什么?测试类代码:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringTrainApplicationTests {

    @Test
    public void contextLoads() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Myconfig.class);
        Object personBeanFactory = applicationContext.getBean("personBeanFactory");
        System.out.println(personBeanFactory.getClass() );
    }

}

运行结果:
class com.snail.tool.bean.Teacher

以上便是4中方式,往IOC容器中注册Bean的方法刚开始学习,慢慢做积累;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值