JAVASpring

手动向Spring容器中注入对象

手动向Spring容器中注入对象的方法有很多,本文将简单阐述其中的四种

1. beanFactory的registerSingleton方法


我们可以实现一个BeanFactory的后置处理器,在其中就可以获得BeanFactory,这样就可以调用registerSingleton方法。
注:此处bean的名字可以自定义,如这里就定义为sherlock。

@Component
public class SherlockBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        beanFactory.registerSingleton("sherlock", new User("sherlock", 18));

    }
}

如果在容器中获取该类

@Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        User sherlock = context.getBean("sherlock", User.class);
        System.out.println(sherlock.toString());
    }

控制台输出:

对象就已成功注入到Spring容器中了。
注:其实在context中也有registerBean方法,可以实现一样的效果。(ApplicationContext其实继承了BeanFactory,所以它也拥有Bean工厂的功能,除此之外ApplicationContext还继承了很多其他的类,拥有一些辅助功能。总的来说,ApplicationContext其实包括了BeanFactory)

2. @Bean注解


在配置类中,使用@Bean注解,返回一个想要注入的对象。@Bean括号中是bean的名字,默认为类名的小写形式。

@Configuration
@ComponentScan("com.sherlock")
public class AppConfig {

    @Bean("sherlock")
    public User user() {
        return new User("sherlock", 19);
    }

}

控制台输出:

3. 使用Factory‘Bean


既然提到了Factory‘Bean,就不得不提到BeanFactory。关于这两个的区别,可以看下我的另一篇文章。https://www.jianshu.com/p/91d21128d2a9
我们可以创建一个类去实现FactoryBean接口

@Component
public class SherlockFactoryBean implements FactoryBean {

    @Override
    public Object getObject() throws Exception {
        return new User("sherlock", 20);
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}
//注意:这个bean的名字是sherlockFactoryBean,但返回的是User类
 User user = context.getBean("sherlockFactoryBean", User.class);

控制台输出:

4. 使用@Import注解


@Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中
@Import的三种用法主要包括:

  • 直接填class数组
@Import({User.class, Order.class})
User user = context.getBean("com.sherlock.pojo.User", User.class);

注意:这样注入的类名为类的全限定名。

  • ImportSelector方式

使用这种方式的这个类必须实现ImportSelector接口

public class SherlockImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //前面可以是和业务相关的逻辑
        //返回需要导入的组件的全类名数组
        return new String[]{"com.sherlock.pojo.User"};
    }
}
  • ImportBeanDefintionRegister方式手动注册bean
public class SherlockImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //需要的业务逻辑
        //指定bean定义信息(包括bean的类型、作用域...)
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(User.class);
        registry.registerBeanDefinition("user",beanDefinition);
    }
}

@Import三种方式的总结

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

5.总结


  • beanFactory的registerSingleton方法
  • @Bean注解
  • FactoryBean
  • @Import