spring 动态注册bean

spring 动态注册bean

如果应用代码需要注册没有被spring容器管理的代码,则需要使用BeanDefinition实例来实现。spring应用可以注册BeanDefinition通过BeanDefinitionRegistry类的方法。

 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

BeanDefinition

BeanDefinition描述bean实例。其有setter方法用来通过编程的方式设置spring特定字符给bean,如:BeanDefinition #setScope(String scope),设置其他的scope代替缺省的singleton。
这里写图片描述

GenericBeanDefinition

是BeanDefinition 的通用实现。允许指定bean类,特性及构造器参数值和属性值。

这里写图片描述

使用 GenericBeanDefinition加载pojo

public class MyBean {
  private Date date;

  public void doSomething () {
      System.out.println("from my bean, date: " + date);
  }

  public void setDate (Date date) {
      this.date = date;
  }
}

通过GenericBeanDefinition加载:

public class GenericBeanDefinitionExample {

  public static void main (String[] args) {
      DefaultListableBeanFactory context =
                new DefaultListableBeanFactory();

      GenericBeanDefinition gbd = new GenericBeanDefinition();
      gbd.setBeanClass(MyBean.class);

      MutablePropertyValues mpv = new MutablePropertyValues();
      mpv.add("date", new Date());

      //alternatively we can use:
      // gbd.getPropertyValues().addPropertyValue("date", new Date());
      gbd.setPropertyValues(mpv);

      context.registerBeanDefinition("myBeanName", gbd);

      MyBean bean = context.getBean(MyBean.class);
      bean.doSomething();
  }
}

输出结果:

from my bean, date: Wed Jan 17 20:20:58 CDT 2018

使用 BeanDefinitionBuilder 加载pojo

使用这种方式的区别是 BeanDefinitionBuilder使用构建模式。

public class MyBean {
  private String str;

  public void setStr (String str) {
      this.str = str;
  }

  public void doSomething () {
      System.out.println("from MyBean " + str);
  }
}

通过BeanDefinitionBuilder加载:

public class BeanDefinitionBuilderExample {

  public static void main (String[] args) {
      DefaultListableBeanFactory beanFactory =
                new DefaultListableBeanFactory();

      BeanDefinitionBuilder b =
                BeanDefinitionBuilder.rootBeanDefinition(MyBean.class)
                                     .addPropertyValue("str", "myStringValue");

      beanFactory.registerBeanDefinition("myBean", b.getBeanDefinition());


      MyBean bean = beanFactory.getBean(MyBean.class);
      bean.doSomething();
  }
}

输出结果:

from MyBean myStringValue

注入其他bean引用

public class MyBean {
  private MyOtherBean otherBean;

  public void setOtherBean (MyOtherBean otherBean) {
      this.otherBean = otherBean;
  }

  public void doSomething () {
      otherBean.doSomething();
  }
}

MyOtherBean

public class MyOtherBean {

  public void doSomething () {
      System.out.println("from other bean ");
  }
}

通过GenericBeanDefinition 加载其他bean引用:

public class InjectingOtherBeans {

  public static void main (String[] args) {
      DefaultListableBeanFactory context =
                new DefaultListableBeanFactory();

      //define and register MyOtherBean
      GenericBeanDefinition beanOtherDef = new GenericBeanDefinition();
      beanOtherDef.setBeanClass(MyOtherBean.class);
      context.registerBeanDefinition("other", beanOtherDef);

      //definine and register myBean
      GenericBeanDefinition beanDef = new GenericBeanDefinition();
      beanDef.setBeanClass(MyBean.class);
      MutablePropertyValues mpv = new MutablePropertyValues();
      mpv.addPropertyValue("otherBean", context.getBean("other"));
      beanDef.setPropertyValues(mpv);
      context.registerBeanDefinition("myBean", beanDef);

      //using MyBean instance
      MyBean bean = context.getBean(MyBean.class);
      bean.doSomething();
  }
}

输出结果:

from other bean 

使用 BeanFactoryPostProcessor

BeanFactoryPostProcessor允许客户端代码自定义bean定义。方法BeanFactoryPostProcessor.postProcessBeanFactory在spring启动过程所有bean定义已经成功加载之后被调用,但仍然没有bean被实例化。

@Configuration
public class MyConfig {
  @Bean
  MyConfigBean myConfigBean () {
      return new MyConfigBean();
  }
}
public class MyConfigBean implements BeanFactoryPostProcessor {

  @Override
  public void postProcessBeanFactory (
            ConfigurableListableBeanFactory beanFactory)
            throws BeansException {

      GenericBeanDefinition bd = new GenericBeanDefinition();
      bd.setBeanClass(MyBean.class);
      bd.getPropertyValues().add("strProp", "my string property");

      ((DefaultListableBeanFactory) beanFactory)
                .registerBeanDefinition("myBeanName", bd);
  }
}
public class MyBean {
  private String strProp;

  public void setStrProp (String strProp) {
      this.strProp = strProp;
  }

  public void doSomething () {
      System.out.println("from MyBean:  " + strProp);
  }
}
public class BeanFactoryPostProcessorExample {

  public static void main (String[] args) {
      AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(MyConfig.class);
      MyBean bean = context.getBean(MyBean.class);
      bean.doSomething();
  }
}

输出结果:

from MyBean:  my string property

使用 BeanDefinitionRegistryPostProcessor

这时BeanFactoryPostProcessor 的一个子接口,其允许注册bean定义。在BeanFactoryPostProcessor#postProcessBeanFactory之前它的方法postProcessBeanDefinitionRegistry 被调用。这个接口更聚焦在BeanDefinition注册,而不是BeanFactoryPostProcessor的一般目的。

@Configuration
public class MyConfig {
  @Bean
  MyConfigBean myConfigBean () {
      return new MyConfigBean();
  }
}
public class MyConfigBean implements BeanDefinitionRegistryPostProcessor {

  @Override
  public void postProcessBeanDefinitionRegistry (BeanDefinitionRegistry registry)
            throws BeansException {

      GenericBeanDefinition bd = new GenericBeanDefinition();
      bd.setBeanClass(MyBean.class);
      bd.getPropertyValues().add("strProp", "my string property");
      registry.registerBeanDefinition("myBeanName", bd);
  }

  @Override
  public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
      //no op
  }
}
public class MyBean {
  private String strProp;

  public void setStrProp (String strProp) {
      this.strProp = strProp;
  }

  public void doSomething () {
      System.out.println("from MyBean:  " + strProp);
  }
}
public class BeanDefinitionRegistryPostProcessorExample {

  public static void main (String[] args) {
      AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(MyConfig.class);

      MyBean bean = (MyBean) context.getBean("myBeanName");
      bean.doSomething();
  }
}

输出结果:

from MyBean:  my string property

总结

通过示例说明了几种动态注册bean的方法。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring中,我们可以使用BeanFactory或者ApplicationContext来动态创建Bean实例。 1. 使用BeanFactory动态创建Bean实例 ```java DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Person.class); builder.addPropertyValue("name", "张三"); builder.addPropertyValue("age", 18); beanFactory.registerBeanDefinition("person", builder.getBeanDefinition()); Person person = (Person) beanFactory.getBean("person"); ``` 以上代码中,我们先创建一个DefaultListableBeanFactory实例,然后使用BeanDefinitionBuilder创建一个BeanDefinition,指定要创建的Bean类型为Person,并设置Bean的属性值(name和age)。最后将BeanDefinition注册BeanFactory中,然后通过getBean()方法获取动态创建的Person实例。 2. 使用ApplicationContext动态创建Bean实例 ```java GenericApplicationContext context = new GenericApplicationContext(); context.refresh(); GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass(Person.class); beanDefinition.getPropertyValues().add("name", "张三"); beanDefinition.getPropertyValues().add("age", 18); context.registerBeanDefinition("person", beanDefinition); Person person = (Person) context.getBean("person"); ``` 以上代码中,我们创建了一个GenericApplicationContext实例,并调用refresh()方法初始化容器。然后创建一个GenericBeanDefinition实例,设置Bean的类型为Person,并设置Bean的属性值(name和age)。最后将BeanDefinition注册到ApplicationContext中,然后通过getBean()方法获取动态创建的Person实例。 总的来说,使用Spring动态创建Bean实例的方法比较灵活,可以根据具体的需求来选择使用BeanFactory或者ApplicationContext。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值