向Spring容器注入Bean的方法

1 如何向Spring容器中注入组件?

向Spring容器中注入组件的方法大概有4种

  1. 包扫描+组件注解标注(@Component、@Controller、@Service、@Repository);
  2. @Bean,导入第三方包中的组件
  3. @Import向Spring容器中快速导入一个组件
  4. 使用Spring提供的FactoryBean(工厂bean)

第一种和第二种都比较熟悉,在项目中使用的比较多,主要介绍下第三种和第四种

2 @Import详解

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

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

}

从@Import注解的源码可以看出,@Import只能注解在类上,并且有3种使用方式

  • 直接填class数组方式
  • 使用ImportSelector方式
  • 使用ImportBeanDefinitionRegistrar方式

2.1 直接使用Class数组填充

这种方式比较简单,直接上图

向Spring容器注入Bean的方法_第1张图片
向Spring容器注入Bean的方法_第2张图片
结果:
向Spring容器注入Bean的方法_第3张图片

注意使用@Import快速导入组件,beanDefinition的name是导入类的全限定名!
向Spring容器注入Bean的方法_第4张图片

2.2 使用ImportSelector方式

1.需要实现ImportSelector接口

public class MyImportSelector implements ImportSelector {
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
                return new String[]{IndexService.class.getName()};
        }
}

2.使用@Import导入

向Spring容器注入Bean的方法_第5张图片

结果:beanDefinition的name也是导入类的全限定名!
向Spring容器注入Bean的方法_第6张图片

2.3 使用ImportBeanDefinitionRegistrar方式

使用ImportBeanDefinitionRegistrar方式其实是自由度最大的一种方式,因为可以拿到Ioc容器做任何自己想做的事情

1.实现ImportBeanDefinitionRegistrar

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                //指定bean定义信息
                RootBeanDefinition beanDefinition = new RootBeanDefinition(IndexService.class);
                //通过Ioc容器注册beanDefinition,这里的registry其实就是DefaultListableBeanFactory
                if (registry instanceof DefaultListableBeanFactory){
                        registry.registerBeanDefinition("zzl",beanDefinition);
                }


        }
}

2.使用@Import导入
向Spring容器注入Bean的方法_第7张图片

结果这种方式是可以自定义beanDefinition的name的
向Spring容器注入Bean的方法_第8张图片

2.4 总结

第一种用法:@Import({ 要导入的容器中的组件 } ):容器会自动注册这个组件,id默认是全类名;
第二种用法:ImportSelector:返回需要导入的组件的全类名数组,springboot底层用的特别多;
第三种用法:ImportBeanDefinitionRegistrar:手动注册bean到容器。

3 使用Spring提供的FactoryBean

FactoryBean就是一个接口,源码如下

public interface FactoryBean {

        String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
        //返回对象实例
        T getObject() throws Exception;
        //返回对象类型
        Class getObjectType();
        //true是单例,false是非单例
        default boolean isSingleton() {
                return true;
        }

}

FactoryBean中定义了一个bean很重要的三个特性:是否单例、bean类型、bean实例!

代码如下

@Componentpublic class FactoryBeanTest implements FactoryBean {
        @Override
        public Object getObject() throws Exception {
                return new IndexService();
        }

        @Override
        public Class getObjectType() {
                return IndexService.class;
        }
}

结果beanDefinition的name是factoryBeanTest,在调用容器getBean的时候获取IndexService实例!
向Spring容器注入Bean的方法_第9张图片

你可能感兴趣的:(spring,spring)