平时开发我们可以使用 Autowired,Resource 注入 spring 容器。
如何使用编程的方式将一个 bean 注入spring 容器 ?

1.set 方法注入

image.png

2.构造方法注入

image.png

3.指定构造方法参数顺序注入

image.png

4.通过 BeanDefinitionBuilder 注入

1.定义一个基础配置类

  1. public class DataSourceConfig {
  2. private String dataSourceName;
  3. private String url;
  4. private String password;
  5. public String getDataSourceName() {
  6. return dataSourceName;
  7. }
  8. public void setDataSourceName(String dataSourceName) {
  9. this.dataSourceName = dataSourceName;
  10. }
  11. public String getUrl() {
  12. return url;
  13. }
  14. public void setUrl(String url) {
  15. this.url = url;
  16. }
  17. public String getPassword() {
  18. return password;
  19. }
  20. public void setPassword(String password) {
  21. this.password = password;
  22. }
  23. }

2.注入spring容器

  1. @SpringBootTest
  2. @RunWith(SpringRunner.class)
  3. public class DatasourceTest {
  4. @Autowired
  5. private ApplicationContext applicationContext;
  6. @Test
  7. public void testInject() {
  8. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DataSourceConfig.class);
  9. beanDefinitionBuilder.addPropertyValue("dataSourceName", "busi");
  10. beanDefinitionBuilder.addPropertyValue("url", "xxx");
  11. beanDefinitionBuilder.addPropertyValue("password", "123456");
  12. DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
  13. beanFactory.registerBeanDefinition("busiDatasourceConfig", beanDefinitionBuilder.getBeanDefinition());
  14. Assert.assertNotNull(applicationContext.getBean(DataSourceConfig.class));
  15. Assert.assertEquals(applicationContext.getBean(DataSourceConfig.class).getDataSourceName(), "busi");
  16. Assert.assertEquals(applicationContext.getBean(DataSourceConfig.class).getPassword(), "123456");
  17. Assert.assertEquals(applicationContext.getBean(DataSourceConfig.class).getUrl(), "xxx");
  18. }
  19. }

5.ObjectProvider

实现宽松的依赖注入,当 spring 容器没有该 Bean 时也不会报错。
什么时候使用ObjectProvider接口?
如果待注入参数的Bean为空或有多个时,便是ObjectProvider发挥作用的时候了。
如果注入实例为空时,使用ObjectProvider则避免了强依赖导致的依赖对象不存在异常;如果有多个实例,ObjectProvider的方法会根据Bean实现的Ordered接口或@Order注解指定的先后顺序获取一个Bean。从而了提供了一个更加宽松的依赖注入方式。

  1. /**
  2. * A variant of {@link ObjectFactory} designed specifically for injection points,
  3. * allowing for programmatic optionality and lenient not-unique handling.
  4. *
  5. * @author Juergen Hoeller
  6. * @since 4.3
  7. */
  8. public interface ObjectProvider<T> extends ObjectFactory<T> {
  9. /**
  10. * Return an instance (possibly shared or independent) of the object
  11. * managed by this factory.
  12. * <p>Allows for specifying explicit construction arguments, along the
  13. * lines of {@link BeanFactory#getBean(String, Object...)}.
  14. * @param args arguments to use when creating a corresponding instance
  15. * @return an instance of the bean
  16. * @throws BeansException in case of creation errors
  17. * @see #getObject()
  18. */
  19. T getObject(Object... args) throws BeansException;
  20. }