注册Bean到IOC容器大致分为4种:
①、包扫描+组件注解(@Controller、@Service、@Repository、@Component)
针对类是我们自己编写的情况
②、@Bean注解
针对导入第三方包里面的类的情况
③、@Import
针对快速导入某一个类的情况,如仅仅只是调用无参构造创建对象。
1)@Import注解直接导入
2)ImportSelector手动导入Bean到容器中
3)ImportBeanDefinitionRegistrar手动注册bean到容器中
④、FactoryBean(Bean工厂)
- 默认获取到的是工厂bean调用getObject方法创建的对象
- 要获取工厂bean本身,我们需要给id前面加一个&
(&FactoryBean)
实战过Spring的人来说,前两种方式可谓是最常见不过了。而后两种方式在开发中比较少见,因此本文主要介绍@Import和FactoryBean这两种方式。
@Import方式
@Import注解源码:
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Import {Class<?>[] value();}
通过源码我们可以发现,@Import注解只能放置在类上,并且有一个value属性,是一个Class类型的数组,我们将需要导入到IOC容器的Bean的字节码放置这个数组中,spring容器就会通过反射创建对象到ioc容器中。
—测试
—配置类
@Configuration@Import({Color.class, Red.class})public class SpringConfig {}
—单元测试
@Testpublic void testApplicationContext2() {ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);String[] names = context.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}}
—测试结果

ImportSelector方式
ImportSelect是一个接口,接口中有一个抽象方法selectImports,返回值为一个String数组,
spring会自动将返回的String数组中的类创建对象到ioc容器中去。
—MyImportSelector代码
public class MyImportSelector implements ImportSelector {// 返回值就是导入到容器中的组件的全类名// AnnotationMetadata:封装了当前标注@Import注解的类的所有注解信息@Overridepublic 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 {}
—单元测试
同上
—测试结果

ImportBeanDefinitionRegistrar
这种方式和ImportSelector方式很类似,都是实现一个接口,然后在重写的方法中编写bean的导入规则。
—MyImportBeanDefinitionRegistrar代码
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {// 编写注册判断规则// 指定Bean的类型,作用域等等RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);// 注册一个bean到ioc容器中,并指定beanNamebeanDefinitionRegistry.registerBeanDefinition("rainBow", beanDefinition);}}
—配置类
@Configuration@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})public class SpringConfig {
—单元测试
同上
—测试结果

FactoryBean
FactoryBean是一个接口,我们需要编写一个类实现它,并重写getObject、getObejctType、isSingleton方法。
- getObject:IOC容器会执行此方法得到Bean,并放到IOC容器中去。
- getObjectType:获取Bean的类型。
- isSingleton:设置Bean是否为单例,返回值为true为单例,false为多例,ioc容器不管理多例的Bean,只负责创建。
Spring与其他框架进行整合的时候使用的就是FactoryBean来创建对象到IOC容器中。
—ColorFactoryBean代码
public class ColorFactoryBean implements FactoryBean<Green> {@Overridepublic Green getObject() throws Exception {return new Green();}@Overridepublic Class<?> getObjectType() {return Green.class;}@Overridepublic boolean isSingleton() {return true;}}
—SpringConfig代码
@Configurationpublic class SpringConfig {@Beanpublic ColorFactoryBean colorFactoryBean() {return new ColorFactoryBean();}}
—单元测试
@Testpublic void testApplicationContext2() {ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);Object bean = context.getBean("colorFactoryBean");System.out.println(bean);System.out.println(bean.getClass());}
—测试结果

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