【Spring Framework】Spring入门教程(四)注册Bean到IOC容器

注册Bean到IOC容器大致分为4种:

①、包扫描+组件注解(@Controller、@Service、@Repository、@Component)

针对类是我们自己编写的情况

②、@Bean注解

针对导入第三方包里面的类的情况

③、@Import

针对快速导入某一个类的情况,如仅仅只是调用无参构造创建对象。

1)@Import注解直接导入

2)ImportSelector手动导入Bean到容器中

3)ImportBeanDefinitionRegistrar手动注册bean到容器中

④、FactoryBean(Bean工厂)

  1. 默认获取到的是工厂bean调用getObject方法创建的对象

  2. 要获取工厂bean本身,我们需要给id前面加一个&(&FactoryBean)

实战过Spring的人来说,前两种方式可谓是最常见不过了。而后两种方式在开发中比较少见,因此本文主要介绍@ImportFactoryBean这两种方式。

@Import方式

@Import注解源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    Class<?>[] value();
}

通过源码我们可以发现,@Import注解只能放置在类上,并且有一个value属性,是一个Class类型的数组,我们将需要导入到IOC容器的Bean的字节码放置这个数组中,spring容器就会通过反射创建对象到ioc容器中。

--测试

--配置类

@Configuration
@Import({Color.class, Red.class})
public class SpringConfig {
}

--单元测试

@Test
public void testApplicationContext2() {
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    String[] names = context.getBeanDefinitionNames();
    for (String name : names) {
        System.out.println(name);
    }
}

--测试结果

img

ImportSelector方式

ImportSelect是一个接口,接口中有一个抽象方法selectImports,返回值为一个String数组,

spring会自动将返回的String数组中的类创建对象到ioc容器中去。

--MyImportSelector代码

public class MyImportSelector implements ImportSelector {
    // 返回值就是导入到容器中的组件的全类名
    // AnnotationMetadata:封装了当前标注@Import注解的类的所有注解信息
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"org.cjw.pojo.Blue", "org.cjw.pojo.Yellow"};
    }
}

--配置类

@Configuration
@Import({Color.class, Red.class, MyImportSelector.class})
public class SpringConfig {
}

--单元测试

同上

--测试结果

img

ImportBeanDefinitionRegistrar

这种方式和ImportSelector方式很类似,都是实现一个接口,然后在重写的方法中编写bean的导入规则。

--MyImportBeanDefinitionRegistrar代码

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        // 编写注册判断规则
        // 指定Bean的类型,作用域等等
        RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
        // 注册一个bean到ioc容器中,并指定beanName
        beanDefinitionRegistry.registerBeanDefinition("rainBow", beanDefinition);
    }
}

--配置类

@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class SpringConfig {

--单元测试

同上

--测试结果

img

FactoryBean

FactoryBean是一个接口,我们需要编写一个类实现它,并重写getObjectgetObejctTypeisSingleton方法。

  • getObject:IOC容器会执行此方法得到Bean,并放到IOC容器中去。

  • getObjectType:获取Bean的类型。

  • isSingleton:设置Bean是否为单例,返回值为true为单例,false为多例,ioc容器不管理多例的Bean,只负责创建。

Spring与其他框架进行整合的时候使用的就是FactoryBean来创建对象到IOC容器中。

--ColorFactoryBean代码

public class ColorFactoryBean implements FactoryBean<Green> {
    @Override
    public Green getObject() throws Exception {
        return new Green();
    }

    @Override
    public Class<?> getObjectType() {
        return Green.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

--SpringConfig代码

@Configuration
public class SpringConfig {

    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}

--单元测试

@Test
public void testApplicationContext2() {
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    Object bean = context.getBean("colorFactoryBean");
    System.out.println(bean);
    System.out.println(bean.getClass());
}

--测试结果

img

通过结果我们可以发现,ioc容器确实有ColorFactoryBean这个对象,但是这个对象的本质是一个Green,即是我们需要创建到ioc容器中的bean。因此我们可以得出结论,只要实现了FactoryBean接口的类,spring都会执行它的getObject方法,将创建的对象放入到ioc容器中,spring和第三方框架的整合靠的就是FactoryBean。

更多详细内容参考这里

posted @ 2021-07-15 11:57  satire  阅读(173)  评论(0编辑  收藏  举报